内存泄漏
上一次以为内存泄露查完了,发现服务器跑了比较长时间后又占用太多内存。刚好这段时间加了一些新的模块,又该查查了。整个服务器模块分的还行,但是中间经过几个人一起写,所以看起来就麻烦了。要解决问题还是必须找到泄露的代码段。在 C/C++ 中,只要用了指针这东西,很多逻辑上的问题也会产生内存泄露。在线下用上次封装 malloc 和 free 的方法测试,找不到产生内存泄露的样例,grep 了一下没有用原来的 malloc 之类的东西啊,那就应该是测试数量太少的问题。没法,从线上的 log 中导入一些天的访问记录,其中包含了一天的访问 url。试着用 Python 写个小程序把一天中所有的 url 依次往线下的服务器发送,这应该有几万条数据了。Python 中这相关的库够多的,可以用的 httplib,或者 webbrowser 模块中的 webbrowser.open(“url_address”,1),不过这得打开系统的默认的浏览器,并且好像还没关掉一个 tab 的接口。最合适这个简单任务的是 urllib 这个模块,下面这样就行了,往线下的服务器狂发请求吧:
for rec in alllogs:
urlstr = rec[0]
#print urlstr
line=line+1
print line,allnum,allnum-line,urlstr
try:
u = urllib.urlopen(urlstr)
except IOError,e:
print ‘connect refused’,e
except UnicodeError,e:
print ‘UnicodeError’,e
res = u.read()
##print u.info()
print “read %d data”%(len(res))
##time.sleep(0.01)
调试方式
Linux 下有一些内存调试工具,不过感觉要么过于复杂要么对代码改动太多,对于在后台这种长时间运行的程序不是很适用。上次提到的封装 malloc,calloc,free 这些函数的检测方法本来是挺好的,但是有两个问题:
1.用于存储内存信息的空间是用数组的,其大小运行时候就固定。 2.不适合多线程程序。
如果用上面所有的 url 向服务器发送完毕后,再来检查输出文件不可行,因为运行中超过了数组的最大记录数后面的检测就没办法记录下来了。对于第二个问题,这个服务器模型是一种简单的多线程并发,启动时设定其启动线程的数目,多个线程排队,一个线程处理一个请求所以之间并无过多的交互。如果保证一个线程运行过程中不会出现内存泄漏,那应该就没问题了。调试的时候在每一个线程开始跑的时候就启动清空上面的记录内存申请和释放的数组,如果某个一个 url 请求产生了泄漏就停下来查看生成的 meminfo.xls。这样跑完几万个 url 后,发现一些代码问题。这些 bug 要是通过人来审查代码不可能查出来,所以测试还是非常重要。其中一部分代码错误是使用了 C 写了一些基本的数据结构,这些里面有的使用了 malloc 来动态调整空间大小,用起来倒是比较方便,但是用完后必须显式地释放掉。这和指针的问题是一样的:何时何地释放。调试后会在代码中加入了很多语句,打印信息、脚手架位置等等,这可以用下面这些命令来替换成空白或者注释。
grep debug_str -rl ./*.c | xargs sed -i “s/debug_str/substr/g”