在前一篇在Qt中使用asan检测内存泄漏(一)-CSDN博客中,我介绍了如何在QT程序里集成asan。一个真实的项目往往包含多个so库。asan如何检查这些库的内存使用呢?这是本篇博文回答的问题。
这里我们使用gdal3.5.3作为so库示例。为了回答上面的问题,我故意在其源码中制造一处内存泄漏点,然后编译并安装gdal。再在我的Qt程序里集成gdal库。最后通过asan检测运行的程序,观察内存检测的结果。
目录
[1 制造内存泄漏点](#1 制造内存泄漏点)
[2 编译gdal并配置.bashrc](#2 编译gdal并配置.bashrc)
[2.1 编译](#2.1 编译)
[2.2 配置.bashrc](#2.2 配置.bashrc)
[3 编译Qt程序](#3 编译Qt程序)
[4 运行程序并观察asan输出](#4 运行程序并观察asan输出)
[5 总结](#5 总结)
1 制造内存泄漏点
在gdal-3.5.3/frmts/gdalallregister.cpp的GDALAllRegister函数开头增加malloc,但是不释放:

2 编译gdal并配置.bashrc
2.1 编译
编译gdal也要支持asan。具体参考CMake编译gdal3.5.3_gdal 3.5.-CSDN博客中Debug版(带asan)的描述。但是由于我已经在/opt/gdal里安装了一个"正常"(无内存泄漏)的gdal版,所以这里把含有内存泄漏的gdal安装在另一个路径/opt/1gdal1路径下。
2.2 配置.bashrc
此外,程序运行不能再调用"正常"的gdal库,所以还要修改~/.bashrc,把LD_LIBRARY_PATH中的gdal路径改为/opt/1gdal1/lib64:

然后运行 source ~/.bashrc使之生效。
3 编译Qt程序
Qt程序与在Qt中使用asan检测内存泄漏(一)-CSDN博客的项目相比,只有两处区别:
1)pro文件里不再依赖/opt/gdal/,而是/opt/1gdal1/
bash
INCLUDEPATH += /opt/1gdal1/include
LIBS += -L/opt/1gdal1/lib64 -lgdal
2)恢复delete \[\] pImgData;这段代码,因为本文研究的是gdal库带来的内存泄漏,而不是项目的main函数自己带来的泄漏。
程序已打包上传【免费】asan检测gdal库的内存泄漏示例资源-CSDN下载
4 运行程序并观察asan输出
运行程序:
bash
ASAN_OPTIONS=detect_leaks=1 ./ASAN
由于我的程序的main函数里调用了GDALAllRegister()函数,所以必然造成内存泄漏:
cpp
int main(void)
{
GDALAllRegister();
......
输出:

可见,asan准确输出了内存泄漏的位置
5 总结
只要在
1)编译gdal源码时明确使用asan,
2)在.bashrc中明确调用使用了asan的库,
3)在pro文件里(通过asan.pri)明确使用asan,并链接使用asan的gdal库,
4)运行程序是明确ASAN_OPTIONS=detect_leaks=1
就能探测到gdal库的泄漏位置。
最后不要忘记删除这个有问题的gdal库,进入源码目录下的build文件夹,然后输入
sudo xargs rm -v < install_manifest.txt
并修改.bashrc。