gcc -fsanitize=address检测到的间接内存泄漏是否需要关注?
问题结论与排查方案
首先可以明确的基本判断
- 调用栈起始于
libasan.so完全是正常现象,不是系统库泄漏:AddressSanitizer会hook程序所有的内存分配、释放接口,所有内存分配的栈顶都会出现libasan的内部符号,这部分和泄漏根因无关。 - 间接泄漏完全需要你负责处理,不属于误报:ASAN定义的「间接泄漏」指的是内存块本身没有被直接丢弃,但是它的唯一引用被持有在另一个已经泄漏的内存块上,最终仍然会导致内存无法被系统回收,长时间运行的程序会出现持续内存上涨,必须修复。
结合你提供的调用栈的定位方向
从调用栈可以直接看出泄漏的内存链路:
- 泄漏的16字节是
std::vector<std::pair<char, int>>容器申请的内存 - 这个vector是
Hitbrief类的成员,在Hitbrief的拷贝构造函数中被拷贝创建 - 这个拷贝生成的
Hitbrief对象最终被存入了std::map<Hitbrief, int>的红黑树节点中,触发点是你调用了map的operator[]方法
你只需要针对以下几个点排查即可:
- 持有
Hitbrief的这个std::map对象本身是否被正常释放?比如是不是用new创建了map对象却没有对应的delete,或者是全局map实例在程序退出时被跳过了析构? Hitbrief类内部如果有自定义指针成员、智能指针成员,有没有出现循环引用的情况导致对象无法被正常析构?- 有没有逻辑分支直接丢弃了map对象的引用/指针,导致后续没有机会释放容器?
快速排查技巧
你可以在Hitbrief类的构造函数、析构函数中增加计数日志,对比程序运行全程Hitbrief的构造次数和析构次数,很快就能定位到是否有实例漏释放,再反向找持有这些实例的上层容器即可。
内容的提问来源于stack exchange,提问作者Kemin Zhou
相关产品推荐
相关产品推荐

