线上服务器脚本内存泄漏问题排查

前一阵子在做对输入法移动端服务器失败率监控的过程中使用C++编写了一个脚本。由于监控脚本就是一个死循环,希望可以长时间运行。但是没运行2天多,监控程序就失效了。到虚拟机上一看原来是监控脚本已经在虚拟机上崩溃,通过分析崩溃文件大致原因是因为内存泄漏的问题。然后观察机器的运行过程发现脚本每次循环的时候都会有大搞90kb的内存泄漏。

查看监控程序的源码:

啥也没有啊?就是创建了一个线程,干完活后释放掉了。为什么会有这么大的内存泄漏呢?

初步怀疑是createThread的问题,查了一下输入法的代码大量使createThread的情况,难道是它,不会吧!

在网上搜了一下createThread内存泄漏,果然存在这种情况。内存泄露存在的原因,是由CreateThead创建的线程不会去检查CRT的TLS数据是否需要释放。

在了解了CreateThread导致内存泄露的原因后,我简单考虑了一下避免这种内存泄露的方法。

首先老老实实的使用_beginthead(ex)函数,是最稳妥的办法。

其次能否避免使用CRT中依赖TLS的函数呢?

也许可以,但是我们所书写的代码,不完全是我们自己在用,而且我们CreateThead所创建的线程,也不一定跑的都是自己的代码,例如我们提供一个库给别人使用,难道还要特别说明不允许使用errno/localtime等函数么?因此这个方法是不建议的。


如果我想用CreateProcess,或者我所使用的底层库使用的是CreateProcess函数,我又不可避免的会使用依赖于TLS的VC运行时库函数,有什么办法能保证ptd会被释放呢?

我们可以自己释放ptd。前面的分析可以看出,_endthread()函数调用了_freeptd(ptd)来释放ptd,因此我们可以在线程函数的末 尾显示的调用_endthread()或_endthreadex(retcode)函数来释放ptd。在查看了_freeptd函数的代码后,我发现如 果传入参数是NULL,_freeptd函数释放的就是caller线程的ptd,因此也可以直接调用_freeptd来执行清理。

另外,我们也可以自动释放ptd。在VC的工程属性中,可以选择运行时库的类型,如图:


如果我们选择/MTd或/MDd,运行时库以动态方式链接,即我们的程序会使用传说中的msvcrt*.dll。在这个dll的入口函数中,会在 DLL_THREAD_ATTACH时为attach的线程初始化TLS数据,在DLL_THREAD_DETACH时为detach的线程调用 _freeptd函数执行清理。因此如果我们使用VC的动态库,使用CreateThread和使用_beginthread是同样安全的。

总结一下,避免CreateThread引发泄露,大致有几种方法:

1. 使用_beginthread/_beginthreadex函数创建线程

2. 在线程函数return前,显示调用_endthread/_endthreadex函数

3. 在线程函数return前,显示调用_freeptd(NULL),此方法在C语言中有效

4. 使用/MTd或/MDd参数



原文链接

如需转载该篇文章,请注明来自“搜狗测试”


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值