Added stack trace to LeakCheck on windows. Re-enabled stack

trace printing (though off as default).
This commit is contained in:
hiker
2014-04-11 08:00:10 +10:00
parent 502987d3e0
commit 27a5959fcc
3 changed files with 79 additions and 40 deletions

View File

@@ -198,16 +198,24 @@
if(last_separator)
last_separator[0] = '\0';
// Finally initialize the symbol handler.
BOOL bOk = _SymInitialize(hProcess, filepath ? filepath : NULL, TRUE);
if(!bOk)
{
Log::warn("CrashReporting", "SymInitialize() failed");
FreeLibrary(hImageHlpDll);
return;
}
// Since the stack trace can also be used for leak checks, don't
// initialise this all the time.
static bool first_time = true;
_SymSetOptions(SYMOPT_LOAD_LINES);
if (first_time)
{
// Finally initialize the symbol handler.
BOOL bOk = _SymInitialize(hProcess, filepath ? filepath : NULL, TRUE);
if (!bOk)
{
Log::warn("CrashReporting", "SymInitialize() failed");
FreeLibrary(hImageHlpDll);
return;
}
_SymSetOptions(SYMOPT_LOAD_LINES);
first_time = false;
}
}
// Get the stack trace

View File

@@ -18,20 +18,26 @@
#include "utils/leak_check.hpp"
#include "utils/crash_reporting.hpp"
#include "utils/log.hpp"
#include "utils/synchronised.hpp"
#include "utils/ptr_vector.hpp"
#include "utils/string_utils.hpp"
#include "utils/synchronised.hpp"
#ifdef DEBUG
/** Switch this to 1 to get the backtrace of the leaks (slows down execution a little)
Atm only implemented for OSX */
#define GET_STACK_TRACE 0
* Atm only implemented for OSX and windows. */
#undef GET_STACK_TRACE
Synchronised<int> m_lock_stacktrace;
#if (GET_STACK_TRACE == 1) && defined(__APPLE__)
# include <Availability.h>
# include <execinfo.h>
#ifdef GET_STACK_TRACE
# ifdef __APPLE__
# include <Availability.h>
# include <execinfo.h>
# endif
#endif
#include <iostream>
@@ -46,14 +52,18 @@ namespace MemoryLeaks
// ------------------------------------------------------------------------
AllocatedObject::AllocatedObject()
{
#if (GET_STACK_TRACE == 1) && defined(__APPLE__)
#ifdef GET_STACK_TRACE
# if defined(__APPLE__)
const int max_size = 32;
void* callstack[max_size];
m_stack_size = backtrace(callstack, max_size);
m_stack = backtrace_symbols(callstack, m_stack_size);
#else
m_stack = NULL;
# elif defined(WIN32)
m_lock_stacktrace.lock();
CrashReporting::getCallStack(m_stack);
m_lock_stacktrace.unlock();
# endif
#endif
addObject(this);
} // AllocatedObject
@@ -68,19 +78,24 @@ namespace MemoryLeaks
*/
void AllocatedObject::print() const
{
//m_object->print();
if (m_stack == NULL)
#ifdef GET_STACK_TRACE
# if defined(__APPLE__)
for (int i = 0; i < m_stack_size; ++i)
{
printf(" (No stack information available)\n");
Log::error("LeakCheck", " %s\n", m_stack[i]);
}
else
# elif defined(WIN32)
std::vector<std::string> calls = StringUtils::split(m_stack, '\n');
// Ignore the first 4 entries, which are: empty, getCallStack(),
// AllocatedObject(),LeakCheck()
for (unsigned int i = 4; i < calls.size(); ++i)
{
for (int i = 0; i < m_stack_size; ++i)
{
printf(" %s\n", m_stack[i]);
}
Log::error("LeakCheck", " %s", calls[i].c_str());
}
# endif
#else
printf(" (No stack information available)\n");
#endif
} // print

View File

@@ -20,21 +20,32 @@
#ifndef HEADER_LEAK_CHECK_HPP
#define HEADER_LEAK_CHECK_HPP
#include "utils/log.hpp"
#include <stdio.h>
#ifdef DEBUG
#include "utils/log.hpp"
#ifdef WIN32
# include <string>
# include <vector>
#endif
namespace MemoryLeaks
{
class AllocatedObject
{
#if defined(__APPLE__)
/** Keep stack information if available (OSX only). */
char **m_stack;
/** Keeps stacksize information if available (OSX only). */
int m_stack_size;
#elif defined(WIN32)
/** Keep the stack information the way it is returned by windows,
* a flat string, which will be split when printing it. */
std::string m_stack;
#endif
public:
AllocatedObject();
virtual ~AllocatedObject();
@@ -50,19 +61,24 @@ namespace MemoryLeaks
} // namespace MemoryLeaks
#define LEAK_CHECK() \
class LeakCheck : public MemoryLeaks::AllocatedObject\
{ public:\
virtual void print() const\
{ \
Log::error("LeakCheck", "Undeleted object at %s : %i\n", __FILE__, __LINE__); \
} \
virtual ~LeakCheck() {} \
}; \
LeakCheck leack_check_instance;
#define LEAK_CHECK() \
class LeakCheck : public MemoryLeaks::AllocatedObject \
{ \
public: \
virtual void print() const \
{ \
Log::error("LeakCheck", "Undeleted object at %s : %i", \
__FILE__, __LINE__); \
AllocatedObject::print(); \
} \
virtual ~LeakCheck() {} \
}; \
\
LeakCheck m_leack_check_instance;
#else
// No debugging
#define LEAK_CHECK()
#endif