Added stack trace to LeakCheck on windows. Re-enabled stack
trace printing (though off as default).
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user