记一次内存泄露调查

近期一个应用程序出现32k/4~5s的内存持续泄露。

排查思路:

  1. 在从业务链路上,从上游到下游,梳理数据流通路。
    在其数据收发的几个类的几个方法上,通过函数重写,添加hack函数(不做业务处理),分段查看泄露情况。

  2. 在proc目录下,查看进程的mappings信息。统计当中{heap},{stack},发现{heap}是有缓慢增加的;其他段是维持固定的。

  3. 通过其他demo应用,进行交叉测试,发现demo没有泄露。验证了依赖的三方库,通信库,没有泄露。

  4. 整个工程当中搜索 new, malloc, calloc等,跟踪其对象释放情况。

  5. shared_ptr最推荐的还是用make_shared的初始化方法。shared_ptr和new配合使用也不存在对象泄露问题。

  6. 最后发现,是有一个消息队列,stl::queue. 有两个线程通过一把锁操作这个队列。一个线程每次执行loop中push_back两次, 另外一个线程一次执行中 pop_front一次。两个线程通过 sem_post 和semwait同步。
    最后的结果 queue中push进来的消息积压,无法及时消费,导致内存持续增大。 msg内容是log,所以前期没有关注到。

### 如何使用内存钩子防止内存泄漏 为了有效预防和检测C++或C中的内存泄漏,可以利用内存分配挂钩(hook)。通过设置自定义的内存分配函数来监控所有的`malloc`、`free`等调用情况。当程序结束运行时,如果存在未释放的动态分配空间,则表明发生了内存泄漏。 #### 使用 `_CrtSetDbgFlag()` 和 `_CrtSetAllocHook()` 在Windows平台下开发的应用可以通过Microsoft Visual Studio提供的调试库接口实现这一功能。下面是一个简单的例子展示怎样安装一个全局的分配钩子并启用详细的报告模式: ```cpp #define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> // For debugging tools like _CrtDumpMemoryLeaks() #include <iostream> // 自定义分配钩子函数原型声明 int my_alloc_hook(int allocType, void* userData); void GetMemory(char*& p, int num) { p = (char*)malloc(sizeof(char)*num); } int main() { // 启动更严格的内存泄露检查 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); // 安装自定义的分配钩子 _CrtSetAllocHook(my_alloc_hook); char* str = nullptr; GetMemory(str, 100); // 这里会触发一次内存分配操作 std::cout << "Memory leak test!" << std::endl; // 输出当前存在的任何内存泄漏信息到控制台 _CrtDumpMemoryLeaks(); return 0; } ``` 对于上述代码片段中提到的自定义分配钩子函数 `my_alloc_hook` 的定义如下所示: ```cpp #include <stdio.h> static long allocationNumber = 0L; /* 录已发生的分配次数 */ static size_t totalBytesAllocated = 0; /* 统计总共分配了多少字节 */ /* 自定义分配钩子函数 */ int my_alloc_hook(int allocType, void* userData){ switch(allocType){ case _HOOK_MALLOC: ++allocationNumber; printf("Allocation #%ld\n", allocationNumber); break; case _HOOK_FREE: --allocationNumber; printf("Freeing memory...\n"); break; default: ; } return TRUE; } ``` 此方法不仅能够帮助开发者追踪每一个新创建的对象及其大小,还可以录每次释放的情况。一旦发现有对象未能正常回收,就可以进一步调查其原因所在[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值