通过asan和tsan对内存越界、内存泄露、死锁等进行检测

本文介绍了AddressSanitizer(ASan)和ThreadSanitizer(TSan)这两种内存错误和并发问题检测工具。ASan帮助检测内存越界、内存泄漏等问题,而TSan则用于检测数据竞争和死锁。与Valgrind/Helgrind相比,ASan/TSan具有更低的性能开销和更高的准确性。文章详细说明了ASan和TSan的使用方法,包括CMakeLists配置、内存越界、内存泄漏、use after free、double free、data race和死锁检测的示例和报告。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 介绍

AddressSanitizer(ASan)是一种内存错误检测工具,可以帮助我们发现C/C++程序中的内存错误,如缓冲区溢出、使用已释放的内存、内存泄露等。

ThreadSanitizer(简称TSan)是一种用于检测并发程序中数据竞争的工具。可以帮助我们多线程数据竞争、死锁检测等。

GCC从4.8版本开始支持Address和Thread Sanitizer,简单的在makefile中追加相关的编译选项,就可以通过Address和Thread Sanitizer帮我们查找各种隐藏的bug。

2 ASan/TSan和另一个工具Valgrind/Helgrind的对比

优势:
  • 性能开销:

ASan/TSan的性能开销通常比Valgrind/Helgrind低,ASan/TSan是通过编译时插入的代码来检测内存错误,因此在运行时的性能开销相对较小。相比之下,Valgrind/Helgrind通过将被检测程序的二进制代码解释执行,因此通常会引入更大的性能开销。

  • 精确性:

ASan/TSan在编译时会直接插入检测代码到目标程序中,能够提供更准确的内存错误位置信息和更好的报告。Valgrind/Helgrind精度也很高,但由于其工作原理是基于程序外挂的方式,可能会产生一些误报或漏报。

劣势:
  • 便利性:ASan/TSan需要对被测试程序和模块重新编译,而Valgrind/Helgrind可以以外挂方式运行

3 AddressSanitizer使用方法

CMakeLists.txt中启用ASan:

target_compile_options(hash_table_test PRIVATE -fsanitize=address -g1 -O0)
target_link_libraries(hash_table_test ${depend_libs} asan pthread)

启动时通过LD_PRELOAD预加载asan避免so加载顺序问题:

export LD_PRELOAD=/usr/lib/gcc/x86_64-linux-gnu/9/libasan.so
3.1 内存越界

内存越界示例代码

内存越界检测报告

3.2 内存泄漏

内存泄露示例代码

内存泄露检测报告

3.3 use after free

非法指针访问示例代码

非法指针访问检测报告

3.4 double free

double free示例代码

double free检测报告

4 ThreadSanitizer使用方法

4.1 简单的代码示例:

CMakeLists.txt中启用TSan:

target_compile_options(hash_table_test PRIVATE -fsanitize=thread -g1 -O0)
target_link_libraries(hash_table_test ${depend_libs} tsan pthread)

启动时通过LD_PRELOAD预加载tsan避免so加载顺序问题:

export LD_PRELOAD=/usr/lib/gcc/x86_64-linux-gnu/9/libtsan.so
4.2 data race检测

测试测序启动后,tsan能检测到share data的数据竞争(data race)。从输出的信息能看出,T1/T2线程对share_data的操作时机点,并且没有同步操作。

对于data race可以通过mutex或atomic改进。

4.3 死锁检测

上面的示例代码,虽然thread1在thread2运行前就会退出,实际上不会发生死锁,但代码逻辑上的潜在死锁问题,tsan能帮我们检查出来。

从输出的信息能看到M28和M29两把锁的持有状况和相关的线程T1/T2的创建信息。

注意:tsan的死锁检测是基于运行态(data race也一样),只有当thread2_main函数被执行到时,死锁问题才能被发现,所以需要完备的测试用例覆盖尽可能多的分支。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值