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

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

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

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

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

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

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

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

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

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

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

在多线程环境下使用局部数组引起的假“内存泄漏”》上有6条评论

  1. zxboy

    我是名JAVA程序员 你现在可以说是在写类似tomcat,apache的软件 虽然想法还不成熟 代码还不规范话外 你的编程能力很强 而且年龄 还很小 可见你的刻苦和聪明!呵呵 坚持自己信仰 你会很牛的

    回复
  2. kiki

    我也做了一个类似的webserver,交流一下吧:

    http://sites.google.com/site/cxtools/socket-1

    线程有一个默认的栈,所有的函数的跳转和执行,函数中局部(自动)变量的生成和销毁都是在栈上的。一个函数在执行的时候,其局部变量会一直在栈上,直到函数退出时(或者退出后,视具体的函数调用约定)由自己或者调用该函数的代码来释放。如果你的局部变量很多,建议就不要放在栈上了,你可以放在堆上,这样你对他的控制更灵活一些,可以随时申请和释放,而局部变量显然是无法控制其释放的。

    回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>