我inheritance了一些遗留代码,似乎有某处的内存泄漏。 我的第一本能就是编译
-faddress=sanitize -fno-omit-frame-pointer
让地址清理工具的家庭find我的泄漏。 然而,我非常失望。 我希望得到某种运行时错误信息(类似于你读或写内存时地址清理器的错误)。 泄漏消毒剂似乎没有做任何泄漏检查分析,直到程序成功完成。 我的问题是我inheritance的代码有几个线程,并没有被devise为join所有的准备软着陆。
我用一个简单的例子简化了我的问题:
#include <thread> #include <chrono> #include <iostream> bool exit_thread = false; void threadFunc() { while(!exit_thread) { char* leak = new char[256]; std::this_thread::sleep_for(std::chrono::seconds{1}); } } int main() { std::thread t(threadFunc); std::cout << "Waiting\n"; std::this_thread::sleep_for(std::chrono::seconds{5}); exit_thread = true; std::cout << "Exiting\n"; //Without joining here I do not get the leak report. t.join(); return 0; }
我编译这个
clang++ leaker.cpp -fsanitize=address -fno-omit-frame-pointer -g -O0 -std=c++1y -o leaker
然后跑了
ASAN_OPTIONS='detect_leaks=1' LSAN_OPTIONS='exitcode=55:report_objects=true:log_threads=true:log_pointers=true' ./leaker
(我有点疯狂在“LSAN_OPTIONS”在这里,因为我在玩耍…没有任何选项做了我想要的东西,但是在学习泄漏时退出)。
正如在代码中所提到的,如果我join这个线程然后退出程序,我会得到一个漂亮的泄漏报告。 否则我什么也得不到。 正如你可以在遗留的代码库中跟踪10-100个线程,并使它们全部很好地下降一样笨拙。
几年前,我记得使用Visual Leak Detector,并且运气好,因为它会产生所有潜在的内存泄漏的报告(而且我不记得必须把所有的东西都弄好)。 问题是这个工具只适用于Windows,而我的代码只适用于Linux。 我可以让LeakSanitizer工具做类似的事吗?
LeakSanitizer( sanitizer / lsan_interface.h )的公共接口具有各种功能,可以满足您的需求。 函数__lsan_do_leak_check()
执行检查,并在发现泄漏时终止。 还有__lsan_do_recoverable_leak_check
不终止,可以多次调用。
考虑对您的程序进行这种修改:
#include <thread> #include <chrono> #include <iostream> #include <sanitizer/lsan_interface.h> bool exit_thread = false; void threadFunc() { while(!exit_thread) { char* leak = new char[256]; std::this_thread::sleep_for(std::chrono::seconds{1}); } } int main() { std::thread t(threadFunc); std::cout << "Waiting\n"; std::this_thread::sleep_for(std::chrono::seconds{5}); exit_thread = true; std::cout << "Exiting\n"; //Without joining here I do not get the leak report. //t.join(); __lsan_do_recoverable_leak_check(); std::cout << "Done\n"; return 0; }
输出:
Waiting Exiting ================================================================= ==29240==ERROR: LeakSanitizer: detected memory leaks Direct leak of 1024 byte(s) in 4 object(s) allocated from: #0 0x4d9a30 in operator new[](unsigned long) (leaker+0x4d9a30) #1 0x4dc663 in threadFunc() leaker.cpp:12:20 #2 0x4dffe3 in void std::_Bind_simple<void (*())()>::_M_invoke<>(std::_Index_tuple<>) /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/functional:1530:18 #3 0x4dff94 in std::_Bind_simple<void (*())()>::operator()() /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/functional:1520:16 #4 0x4dfcc8 in std::thread::_Impl<std::_Bind_simple<void (*())()> >::_M_run() /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/thread:115:13 #5 0x7f0a9664034f in execute_native_thread_routine /build/gcc-multilib/src/gcc-5.2.0/libstdc++-v3/src/c++11/thread.cc:84 SUMMARY: AddressSanitizer: 1024 byte(s) leaked in 4 allocation(s). Done terminate called without an active exception Aborted