diff options
Diffstat (limited to 'lib/common/DebugMemLeakFinder.cpp')
-rw-r--r-- | lib/common/DebugMemLeakFinder.cpp | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/lib/common/DebugMemLeakFinder.cpp b/lib/common/DebugMemLeakFinder.cpp index 72891cd1..ecc4eb12 100644 --- a/lib/common/DebugMemLeakFinder.cpp +++ b/lib/common/DebugMemLeakFinder.cpp @@ -7,11 +7,18 @@ // // -------------------------------------------------------------------------- +<<<<<<< HEAD #ifndef BOX_RELEASE_BUILD #include "Box.h" +======= +#include "Box.h" + +#ifdef BOX_MEMORY_LEAK_TESTING + +>>>>>>> 0.12 #undef malloc #undef realloc #undef free @@ -20,11 +27,21 @@ #include <unistd.h> #endif +<<<<<<< HEAD #include <map> #include <stdio.h> #include <string.h> #include <set> #include <cstdlib> // for std::atexit +======= +#include <signal.h> +#include <stdio.h> +#include <string.h> + +#include <cstdlib> // for std::atexit +#include <map> +#include <set> +>>>>>>> 0.12 #include "MemLeakFinder.h" @@ -73,6 +90,16 @@ namespace size_t sNotLeaksPreNum = 0; } +<<<<<<< HEAD +======= +void memleakfinder_report_on_signal(int unused) +{ + // this is not safe! do not send SIGUSR1 to a process + // in a production environment! + memleakfinder_report_usage_summary(); +} + +>>>>>>> 0.12 void memleakfinder_init() { ASSERT(!memleakfinder_initialised); @@ -84,6 +111,24 @@ void memleakfinder_init() } memleakfinder_initialised = true; +<<<<<<< HEAD +======= + + #if defined WIN32 + // no signals, no way to trigger event yet + #else + struct sigaction newact, oldact; + newact.sa_handler = memleakfinder_report_on_signal; + newact.sa_flags = SA_RESTART; + sigemptyset(&newact.sa_mask); + if (::sigaction(SIGUSR1, &newact, &oldact) != 0) + { + BOX_ERROR("Failed to install USR1 signal handler"); + THROW_EXCEPTION(CommonException, Internal); + } + ASSERT(oldact.sa_handler == 0); + #endif // WIN32 +>>>>>>> 0.12 } MemLeakSuppressionGuard::MemLeakSuppressionGuard() @@ -141,6 +186,19 @@ void *memleakfinder_malloc(size_t size, const char *file, int line) return b; } +<<<<<<< HEAD +======= +void *memleakfinder_calloc(size_t blocks, size_t size, const char *file, int line) +{ + void *block = memleakfinder_malloc(blocks * size, file, line); + if (block != 0) + { + memset(block, 0, blocks * size); + } + return block; +} + +>>>>>>> 0.12 void *memleakfinder_realloc(void *ptr, size_t size) { InternalAllocGuard guard; @@ -346,6 +404,88 @@ int memleakfinder_numleaks() return n; } +<<<<<<< HEAD +======= +// Summarise all blocks allocated and still allocated, for memory usage +// diagnostics. +void memleakfinder_report_usage_summary() +{ + InternalAllocGuard guard; + + ASSERT(!sTrackingDataDestroyed); + + typedef std::map<std::string, std::pair<uint64_t, uint64_t> > usage_map_t; + usage_map_t usage; + + for(std::map<void *, MallocBlockInfo>::const_iterator + i(sMallocBlocks.begin()); i != sMallocBlocks.end(); ++i) + { + std::ostringstream buf; + buf << i->second.file << ":" << i->second.line; + std::string key = buf.str(); + + usage_map_t::iterator ui = usage.find(key); + if(ui == usage.end()) + { + usage[key] = std::pair<uint64_t, uint64_t>(1, + i->second.size); + } + else + { + ui->second.first++; + ui->second.second += i->second.size; + } + } + + for(std::map<void *, ObjectInfo>::const_iterator + i(sObjectBlocks.begin()); i != sObjectBlocks.end(); ++i) + { + std::ostringstream buf; + buf << i->second.file << ":" << i->second.line; + std::string key = buf.str(); + + usage_map_t::iterator ui = usage.find(key); + if(ui == usage.end()) + { + usage[key] = std::pair<uint64_t, uint64_t>(1, + i->second.size); + } + else + { + ui->second.first++; + ui->second.second += i->second.size; + } + } + + #ifndef DEBUG_LEAKS + BOX_WARNING("Memory use: support not compiled in :("); + #else + if(usage.empty()) + { + BOX_WARNING("Memory use: none detected?!"); + } + else + { + uint64_t blocks = 0, bytes = 0; + BOX_WARNING("Memory use: report follows"); + + for(usage_map_t::iterator i = usage.begin(); i != usage.end(); + i++) + { + BOX_WARNING("Memory use: " << i->first << ": " << + i->second.first << " blocks, " << + i->second.second << " bytes"); + blocks += i->second.first; + bytes += i->second.second; + } + + BOX_WARNING("Memory use: report ends, total: " << blocks << + " blocks, " << bytes << " bytes"); + } + #endif // DEBUG_LEAKS +} + +>>>>>>> 0.12 void memleakfinder_reportleaks_file(FILE *file) { InternalAllocGuard guard; @@ -549,4 +689,8 @@ void operator delete(void *ptr) throw () internal_delete(ptr); } +<<<<<<< HEAD #endif // BOX_RELEASE_BUILD +======= +#endif // BOX_MEMORY_LEAK_TESTING +>>>>>>> 0.12 |