手撕检测内存泄漏组件

内存泄漏的原因通常是进行了malloc(或类似操作)又没有进行free。

检测内存泄漏需要关注:1、判断是否有内存泄漏。2、内存泄漏发生在哪一行。

宏定义方法制造组件

该方法仅适用于单文件检测内泄漏,因为宏定义只在当前文件中有效。

这里的组件指的是利用宏定义功能将内存操作相关的函数(malloc,free等)在保留原有功能的基础上增添上所需功能的函数。

如何判断是否有内存泄漏?

该组件可以在每次程序malloc的时候根据内存地址生成一个内存相关文件,每次程序free的时候根据内存地址销毁相关文件。最后如果有剩余文件,说明有内存泄漏

如何判断泄漏发生在哪一行?

用__LINE__和__FILE__宏定位发生内存操作的具体代码位置。

如何设置组件开关?

通过设置flag决定是否开启检测组件。

代码:

手撕检测内存泄漏组件_第1张图片

Hook方法制造组件

Hook方法制造组件除了单文件,也适合检测多文件、第三方库等是否存在内存泄漏,以及非第三方库造成的内存泄漏在哪一行等。

Hook在编程中是一种技术,这种技术简单来说就是让函数(也能是类、事件等)在保留原有功能的基础上,拓展功能。相比起宏,函数功能的拓展可以不仅仅在当前文件中,也能在其他文件中。

在本案例用dlsym实现hook,过程如下:

1、定义能容纳原函数的函数类型并构造相关变量。

2、将原函数存储在相关变量中。

3、重新实现与原函数同名的函数,在其中调用相关的函数变量,以此保留原函数的功能,并增加功能。

重点细节:

  1. 有些第三方库的函数(比如printf、getchar),会在底层的代码中调用malloc,为了防止循环调用形成阻塞,需要设置变量和if引导第三方的库的函数调用malloc的时候走的是重定义之前的malloc。
  2. Gcc编译的要加-g选项,-g是给编译的可执行文件添加调试信息(变量名、文件名、行号、类型信息等),方便我们在终端利用addr2line定位发生内存泄漏的行号。
  3. __builtin_return_address函数,会返回函数的地址。参数为0表示当前函数的调用地址。参数为1表示当前函数的调用的那一行所在的函数的地址。一般填0。
  4. 高版本的linux用addr2line识别行号, 传入的地址用自定义的函数ConvertToEL产生,是一个相对地址,相对代码载入内存中的起始地址。如果是低版本的linux则不需要调用该函数、

代码:

手撕检测内存泄漏组件_第2张图片

手撕检测内存泄漏组件_第3张图片

执行结果:

手撕检测内存泄漏组件_第4张图片

你可能感兴趣的:(c语言,c++,linux,安全性测试)