LeakSanitizer:获取 运行 时间泄漏报告?
LeakSanitizer: get run time leak reports?
我继承了一些遗留代码,似乎某处有内存泄漏。我的第一直觉是用
编译
-faddress=sanitize -fno-omit-frame-pointer
让 Address Sanitizer 的工具系列帮我找到漏洞。然而,我非常失望。我希望出现某种 运行 时间错误消息(类似于当您不应该读取或写入内存时地址清理器的错误)。在程序成功完成之前,泄漏消毒剂似乎不会进行任何泄漏检查分析。我的问题是我继承的代码有多个线程,它并不是为了将所有线程都加入到软着陆准备中而设计的。
我在一个简单的例子中简化了我的问题:
#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" 有点疯狂,因为我在玩... none 的选项做了我想要的,但是在得知泄漏后退出)。
如代码中所述,如果我加入线程然后退出程序,我会得到一个非常好的泄漏报告。否则我什么也得不到。正如您可以想象的那样,在遗留代码库 和 中跟踪 10-100 个线程,让它们全部正常运行是很笨拙的。
几年前我记得玩过 Visual Leak Detector 并且运气不错,因为它会生成包含所有潜在内存泄漏的报告(而且我不记得必须很好地删除所有内容) .问题是此工具仅适用于 Windows,而我的代码仅适用于 Linux。我可以让 LeakSanitizer 工具做类似的事情吗?
LeakSanitizer (sanitizer/lsan_interface.h) 的 public 接口具有多种功能,可满足您的需要。函数 __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
我继承了一些遗留代码,似乎某处有内存泄漏。我的第一直觉是用
编译-faddress=sanitize -fno-omit-frame-pointer
让 Address Sanitizer 的工具系列帮我找到漏洞。然而,我非常失望。我希望出现某种 运行 时间错误消息(类似于当您不应该读取或写入内存时地址清理器的错误)。在程序成功完成之前,泄漏消毒剂似乎不会进行任何泄漏检查分析。我的问题是我继承的代码有多个线程,它并不是为了将所有线程都加入到软着陆准备中而设计的。
我在一个简单的例子中简化了我的问题:
#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" 有点疯狂,因为我在玩... none 的选项做了我想要的,但是在得知泄漏后退出)。
如代码中所述,如果我加入线程然后退出程序,我会得到一个非常好的泄漏报告。否则我什么也得不到。正如您可以想象的那样,在遗留代码库 和 中跟踪 10-100 个线程,让它们全部正常运行是很笨拙的。
几年前我记得玩过 Visual Leak Detector 并且运气不错,因为它会生成包含所有潜在内存泄漏的报告(而且我不记得必须很好地删除所有内容) .问题是此工具仅适用于 Windows,而我的代码仅适用于 Linux。我可以让 LeakSanitizer 工具做类似的事情吗?
LeakSanitizer (sanitizer/lsan_interface.h) 的 public 接口具有多种功能,可满足您的需要。函数 __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