文章目录
- 前言
- 初始代码
- 链接asan动态库
- 静态方式链接
- 额外说明
- 小结
前言
ASAN是一个内存问题检测工具
类似的还有valgrind, 但是valgrind运行时会占用非常多的内存
初始代码
#include<stdio.h>
#include"arcojson.h"
int leak_func()
{
arco_json* jtest = new_json_object();
json_object_add(jtest, "name", new_json_string("arco~"));
printf("%s\n", json_to_string(jtest));
}
int main()
{
leak_func();
return 0;
}
初始CMakeLists.txt
project(asantest)
cmake_minimum_required(VERSION 3.16)
add_executable(asantest main.c arcojson.c)
这个arcojson.c来源于另一篇文章,是一个简单的c json库
https://blog.csdn.net/weixin_44919664/article/details/136113774
暂时还没有链接asan库
编译运行, 输出
./asantest
{"name":"arco~"}
链接asan动态库
更改CMakeLists.txt
project(asantest)
cmake_minimum_required(VERSION 3.16)
add_executable(asantest main.c arcojson.c)
set_target_properties(asantest PROPERTIES LINK_FLAGS "-Wl,-rpath,.:./lib:/lib64 -fsanitize=address -fno-omit-frame-pointer -fsanitize-recover=all")
target_link_libraries(asantest asan)
注意:-Wl,-rpath之间没有空格
参数说明:我使用的是CMake,Makefile原理也一样, 就是增加gcc的编译选项
-static-libasan 用于链接asan的静态库
-fsanitize=address 检测各种内存错误
同类参数:leak undefined thread memory dataflow
-fno-omit-frame-pointer:保留函数调用栈指针,用于asan更准确的定位错误位置
-fsanitize-recover=all:检测到错误时继续运行
(只检测内存泄漏的话可以用lsan
编译运行: 这将直接在控制台上打印检测信息
也可以导出环境变量
export LSAN_OPTIONS=“verbosity=1:log_threads=1:log_path=/home/asan.log:print_cmdline=1:log_exe_name=1”
这将把输出记录在日志文件里
静态方式链接
我记录这篇文档用的是本地环境,但实际开发的时候用的是交叉编译环境,还需要拷贝asan库到运行环境上
因此也试了一下链接静态库的方式
# 动态库大小26k
-rwxr-xr-x 1 root root 26K 7月 7 16:58 asantest
# 静态库大小
-rwxr-xr-x 1 root root 1.4M 7月 7 17:04 asantest
更改CMAke
project(asantest)
cmake_minimum_required(VERSION 3.16)
add_executable(asantest main.c arcojson.c)
set_target_properties(asantest PROPERTIES LINK_FLAGS "-Wl,-rpath,.:./lib:/lib64 -fsanitize=address -fno-omit-frame-pointer -fsanitize-recover=all")
target_link_libraries(asantest asan)
重新编译运行
输出和环境变量同动态库
额外说明
还有个ASAN option但我不确定是干啥的
export ASAN_OPTIONS="halt_on_error=0:use_sigaltstack=0:detect_leaks=1:symbolize=1:malloc_content_size=15:log_path=/home/asan.log:print_cmdline=1:log_exe_name=1"
如果环境上没有ASAN库, 是拷贝来的, 那么运行时还要在终端上导出LD_PRELOAD环境变量(预加载库路径)
export LD_PRELOAD=/xxx/libasan.so.4
小结
个人觉得,内存检测工具也就图一乐,内存泄漏根本无法解决
自己写的代码检查下还行,公司里我负责的模块(约50w行代码)内存泄漏遍地,用asan和valgrind愣是扫不出来