linux中内存泄漏的检测(五)记录内存泄漏的代码

到目前为止,先后通过wrap malloc、new函数重载和计算指针内存大小的方法,基本上满足了对内存泄漏检测的需要。

如果发现了内存泄漏,那么就要找到内存泄漏的地方并且修正它了。

茫茫代码,如何去找?如果能根据未释放的内存找到申请它的地方就好了。

我们今天就是要做这个事情。

想要根据内存地址查出申请者的信息,那么在一开始申请的时候就要建立地址与申请者之间的映射。

1.内存地址

内存地址,是一个unsigned long型的数值,用void *来存储也可以。为了避免类型转换,我使用了void *

2.申请者信息

申请者的信息比较复杂,不是一个类型可以搞定的。它包括哪些内容呢?

在C情况下,主要是需要知道谁调用了__wrap_malloc。但在C++情况下,调用__wrap_malloc的一定是new,这没有什么意义,还需要知道是谁调用了new。再进一步说,new有可能是在构造函数中被调用的,那么很有可能我们真正需要知道的是谁调用了构造函数。

由此可见,仅仅知道是谁调用了__wrap_malloc不够的,我们需要的是整个栈信息。

整个栈包含了很多内容,在这里,我们只记录栈的深度(int)和每一层的符号名(char **)。符号名在整个程序中是唯一的(不管C还是C++)且相对位置是确定的(动态库除外),当程序结束时再根据符号名反推出调用者的文件名和行号。

为什么不直接获取文件名和行号?
因为求符号名的实现比较简单。

3.映射方式

说到映射,首先想到的是map、hash这样的东西。

但需要说明的是,这里是__wrap_malloc函数,是每次程序动态分配空间时必然会走到的地方。

这有什么关系呢?想象一下,在由于某个动态申请内存的操作来到了这个函数,而在这个函数里又不小心申请了一次内存,会怎样呢?在-Wl,--wrap,malloc的作用下又来到了这里,于是开启了“鸡生蛋、蛋生鸡”的死循环中,直到——stack overflow。

所以,在这个函数里能使用的,只能使用栈空间或者全局空间,如果一定要使用堆空间,也必须显示地使用__real_malloc代替new或者malloc。由于在map、hash中会不可避免地使用动态内存空间的情况,还是放弃吧。

怎么办呢?为了避免节外生枝,我这里使用了最简单但是有点笨的方法——数组。

struct memory_record
{
    void * addr;
    size_t count;
    int depth;
    char **symbols;
}mc[1000];

4.怎样获取栈中的符号?

gcc给我们提相应的函数,按照要求调用就行。

char* stack[20] = {
  0};
mc[i].depth = backtrace(reinterpret_cast<
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值