日度归档:2009 年 01 月 28 日

在多线程环境下使用局部数组引起的假“内存泄漏”

呼~~~~一直担忧的问题被一个在班上不怎么聪明的我总算解决了……

    昨晚那位网友说了他朋友的一句话,“要彻底搞清楚C语言的原理,必须要深入到指令一层去理解。你写一行C代码,编译器会生成什么样的指令,要做到心中有数。”我当时还是觉得写好程序不一定要把语言的原理研究得那么深啊。看来我错了,正是因为我对我所用的工具的原理没有深刻把握,才会在很多线程的情况下使用大栈空间的,最终导致了好长时间都不能解决的内存占用问题。

    一直担忧的内存泄漏问题,今天晚上心血来潮就计划立即解决掉它,反正过年也是闲着。我本来直觉上认为内存泄漏现象是和我博客插件里使用了以前做得不怎么规范的CPrettyText数据库才发生的。但今晚的实验证明和它没有关系,它也不存在什么内存泄漏的地方。由此也证明我在编写服务器时用的memory内存泄漏检测工具失效的判断是不成立的。问题根源是在多线程的栈空间分配上。

    这是我多年多线程编程以来都没有了解到的问题。

    首先,为了加快服务器的响应速度,我的homeserver并不是采用一般的双线程监听,而是很多个(例如300)来同时工作的,这么多个线程抢着响应,保证了较快的速度。这些线程从开始工作一直到服务器被重启或者关闭时才结束,也就是说在服务器运行过程中不会去主动释放线程资源。

    然后,我在博客插件里使用了几个几百KB大的局部数组变量,由栈空间分配。有的是直接嵌套在函数內,有的是直接嵌套在if之类的结构体中。之所以使用栈空间的原因是不想使用堆空间去分配,在插件中不能用memory内存泄漏检测工具的分配函数。

    当多个线程被调用,同时进入了博客插件中去时,就分配了一定的栈空间,而这些空间又是不能及时回收的,除非结束服务器或者使用其他内存整理工具。所以就导致了虚拟内存一直增大的现象。

    我一开始也不知道是栈空间上的问题。只是今晚用注释法寻找漏洞时,发现就和它相关了。而且,我还尝试使用一个很大的局部变量,例如int t[KB(1000)];这样不断刷新页面,让多个线程进入到博客插件中,结果发现内存占用飞一般地增大!

    同时,我也得到这样一个推论。原来的homeserver的虚拟内存会随着多个线程进入而使栈空间增大从而导致内存占用增大,而这种增大不会一直持续下去。因为工作的线程数目是有限的,当所有的线程都被使用过时,它们的栈空间都达到了各自的极限,就再也不会增大了。

    不知道我的分析是否正确,请大家指点!