📄 leaktracer.cc
字号:
// (c) 1999 Erwin S. Andreasen <erwin@andreasen.org>// Homepage: http://www.andreasen.org/LeakTracer/#include <stdio.h>#include <string.h>#include <stdlib.h>#include <execinfo.h>#include <pthread.h>#include <time.h>#include <unistd.h>static int new_count, // how many memory blocks do we have leaks_count, // amount of entries in the below array first_free_spot; // Where is the first free spot in the leaks array?static size_t new_size; // total sizestruct Leak { void *addr; size_t size; void *ret[50]; int backtrace_size;}; static Leak *leaks;extern "C" {extern int main();};bool get_stack(int i, void** ptr){ *ptr = 0; switch(i) { case 1: *ptr = __builtin_return_address(2); break; case 2: *ptr = __builtin_return_address(3); break; case 3: *ptr = __builtin_return_address(4); break; case 4: *ptr = __builtin_return_address(5); break; case 5: *ptr = __builtin_return_address(6); break; case 6: *ptr = __builtin_return_address(7); break; case 7: *ptr = __builtin_return_address(8); break; case 8: *ptr = __builtin_return_address(9); break; } if((*ptr == 0) || (*ptr == main)) { return false; } else { return true; }}static void* register_alloc (size_t size) { new_count++; new_size += size; void *p = malloc(size); if (!p) { // We should really throw some sort of exception or call the new_handler fprintf(stderr, "LeakTracer: malloc: %m"); _exit (1); } for (;;) { for (int i = first_free_spot; i < leaks_count; i++) if (leaks[i].addr == NULL) { leaks[i].addr = p; leaks[i].size = size;// get a backtrace, or try#if 0 for (int j = 0; j < 10 ; j++) { bool r = get_stack(j+1, &(leaks[i].ret[j])); if(!r) break; }#endif leaks[i].backtrace_size = backtrace(leaks[i].ret, 50);// leaks[i].ret2 = __builtin_return_address(2); first_free_spot = i+1; return p; } // Allocate a bigger array // Note that leaks_count starts out at 0. int new_leaks_count = leaks_count == 0 ? 16 : leaks_count * 2; leaks = (Leak*)realloc(leaks, sizeof(*leaks) * new_leaks_count); if (!leaks) { fprintf(stderr, "LeakTracer: realloc: %m"); _exit(1); } memset(leaks+leaks_count, 0, sizeof(*leaks) * (new_leaks_count-leaks_count)); leaks_count = new_leaks_count; }}static void register_free (void *p) { if (p == NULL) return; new_count--; for (int i = 0; i < leaks_count; i++) if (leaks[i].addr == p) { leaks[i].addr = NULL; new_size -= leaks[i].size; if (i < first_free_spot) first_free_spot = i; free(p); return; } fprintf(stderr, "LeakTracer: delete on an already deleted value?\n"); abort();}void* operator new(size_t size) { return register_alloc(size);}void* operator new[] (size_t size) { return register_alloc(size);}void operator delete (void *p) { register_free(p);}void operator delete[] (void *p) { register_free(p);}// This ought to run at the very end, but it requires it to be put last on the linker linevoid write_leaks() __attribute__((destructor));void write_leaks() { const char *filename = getenv("LEAKTRACE_FILE") ? : "leak.out"; FILE *fp; if (!(fp = fopen(filename, "w"))) fprintf(stderr, "LeakTracer: Could not open %s: %m\n", filename); else { for (int i = 0; i < leaks_count; i++) if (leaks[i].addr != NULL) { // This ought to be 64-bit safe? fprintf(fp, "%8p ", leaks[i].addr); char **data; data = backtrace_symbols(leaks[i].ret, leaks[i].backtrace_size); for(int j = 0; j < leaks[i].backtrace_size; j++) { fprintf(fp, "%8p ", leaks[i].ret[j]);// fprintf(fp, "%s ", data[j]); } fprintf(fp, " %9ld\n", (long) leaks[i].size); } fprintf(fp, "-------- %6d\n", new_size); fclose(fp); }}class WritePeriodically{public: WritePeriodically();};void* write_loop(void*){ time_t old_time; time_t new_time; old_time = time(0); new_time = time(0); while(1) { while((new_time - old_time) < 60) { sleep(60 - (new_time - old_time)); new_time = time(0); } old_time = new_time; write_leaks(); } return 0;}WritePeriodically::WritePeriodically(){ pthread_t x; pthread_create( &x, 0, write_loop, 0 );}WritePeriodically myWrite;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -