1、利用backtrace 跟踪各种段错误
#include <execinfo.h> #include <iostream> #include <signal.h> void map_dump(void) { char buff[64] = {0x00}; sprintf(buff, "cat /proc/%d/maps", getpid()); system((const char *)buff); } // 打印堆栈信息 void trace_dump(void) { int j, nptrs; void *buffer[100]; char **strings; #define SIZE 1024 nptrs = backtrace(buffer, SIZE); printf("backtrace() returned %d addresses\n", nptrs); /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO) would produce similar output to the following: */ strings = backtrace_symbols(buffer, nptrs); if (strings == NULL) { perror("backtrace_symbols"); exit(EXIT_FAILURE); } for (j = 0; j < nptrs; j++) printf("%s\n", strings[j]); free(strings); } void signal_handler(int signo) { map_dump(); printf("\n=========>>>catch signal %d <<<=========\n", signo); printf("Dump stack start...\n"); trace_dump(); printf("Dump stack end...\n"); signal(signo, SIG_DFL); /* 恢复信号默认处理 */ raise(signo); /* 重新发送信号 */ } void trigger_crash() { int *p = nullptr; *p = 0; } int main(int argc, char *argv[]) { signal(SIGSEGV, signal_handler); signal(SIGABRT, signal_handler); signal(SIGINT, signal_handler); trigger_crash(); // done: return 0; }
2、 利用Asan追踪内存泄漏
1.AddressSanitizer简介
AddressSanitizer(简称ASan)是一个快速的内存错误检测工具。根据谷歌工程师介绍ASan已经在 chromium 项目上检测出了300多个潜在的未知bug,而且在使用 ASan作为内存错误检测工具对程序性能损耗也是及其可观的。
ASan能够检查内存泄露、越界、未初始化、重复释放、缓冲区溢出、堆栈溢出、野指针、线程死锁等问题。
ASan执行速度非常快,根据检测结果显示可能导致性能降低2倍左右,比Valgrind(官方给的数据大概是降低10-20倍)快了一个数量级。
G++添加如下编译选项即可完成检测
-lasan -fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls -O0
选项-fsanitize=address表示使用ASAN库,为了在错误信息中让栈追溯信息更友好,可以加上-fno-omit-frame-pointer选项。
1.Asan检测的问题
主要可以检查的内存问题有:
- Out-of-bounds accesses to heap, stack and globals
- Use-after-free
- Use-after-return (runtime flag ASAN_OPTIONS=detect_stack_use_after_return=1)
- Use-after-scope (clang flag -fsanitize-address-use-after-scope)
- Double-free, invalid free
- Memory leaks (experimental)
Address Sanitizer 会替换malloc和free,如果采用第三方的内存申请库,则无法替换,会造成功能缺失。