Simplified leak checks (removed one unnecessary class), and made
the data structure thread safe to avoid a race condition that would (very infrequently) crash the game. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@11483 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
@@ -1,20 +1,24 @@
|
||||
/*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2011-2012 Marianne Gagnon, Joerg Henrichs
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
#include "utils/leak_check.hpp"
|
||||
|
||||
#include "utils/synchronised.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -25,8 +29,8 @@
|
||||
|
||||
|
||||
#if (GET_STACK_TRACE == 1) && defined(__APPLE__)
|
||||
#include <Availability.h>
|
||||
#include <execinfo.h>
|
||||
# include <Availability.h>
|
||||
# include <execinfo.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
@@ -35,84 +39,98 @@
|
||||
|
||||
namespace MemoryLeaks
|
||||
{
|
||||
/** A set with all currently allocated objects. */
|
||||
Synchronised< std::set<AllocatedObject*> > g_all_objects;
|
||||
|
||||
std::set<MyObject*> g_all_objs;
|
||||
|
||||
void addObj(MyObject* obj)
|
||||
{
|
||||
g_all_objs.insert(obj);
|
||||
}
|
||||
|
||||
void removeObj(MyObject* obj)
|
||||
{
|
||||
g_all_objs.erase(obj);
|
||||
delete obj;
|
||||
}
|
||||
|
||||
MyObject::MyObject(AbstractLeakCheck* objArg)
|
||||
{
|
||||
obj = objArg;
|
||||
// ------------------------------------------------------------------------
|
||||
AllocatedObject::AllocatedObject()
|
||||
{
|
||||
#if (GET_STACK_TRACE == 1) && defined(__APPLE__)
|
||||
const int max_size = 32;
|
||||
void* callstack[max_size];
|
||||
m_stack_size = backtrace(callstack, max_size);
|
||||
|
||||
#if (GET_STACK_TRACE == 1) && defined(__APPLE__)
|
||||
|
||||
const int maxsize = 32;
|
||||
void* callstack[maxsize];
|
||||
stackSize = backtrace(callstack, maxsize);
|
||||
|
||||
stack = backtrace_symbols(callstack, stackSize);
|
||||
m_stack = backtrace_symbols(callstack, m_stack_size);
|
||||
#else
|
||||
stack = NULL;
|
||||
m_stack = NULL;
|
||||
#endif
|
||||
|
||||
}
|
||||
addObject(this);
|
||||
} // AllocatedObject
|
||||
|
||||
void MyObject::print()
|
||||
// ------------------------------------------------------------------------
|
||||
AllocatedObject::~AllocatedObject()
|
||||
{
|
||||
obj->print();
|
||||
removeObject(this);
|
||||
} // ~AllocatedObject
|
||||
// ------------------------------------------------------------------------
|
||||
/** Print the data associated with the objects.
|
||||
*/
|
||||
void AllocatedObject::print() const
|
||||
{
|
||||
//m_object->print();
|
||||
|
||||
if (stack == NULL)
|
||||
if (m_stack == NULL)
|
||||
{
|
||||
printf(" (No stack information available)\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < stackSize; ++i)
|
||||
for (int i = 0; i < m_stack_size; ++i)
|
||||
{
|
||||
printf(" %s\n", stack[i]);
|
||||
printf(" %s\n", m_stack[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // print
|
||||
|
||||
void checkForLeaks()
|
||||
// ========================================================================
|
||||
/** Adds an object to the sets of all allocated objects. */
|
||||
void addObject(AllocatedObject* obj)
|
||||
{
|
||||
|
||||
g_all_objects.lock();
|
||||
g_all_objects.getData().insert(obj);
|
||||
g_all_objects.unlock();
|
||||
} // addObject
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Removes an object from the set of all allocated objects. */
|
||||
void removeObject(AllocatedObject* obj)
|
||||
{
|
||||
g_all_objects.lock();
|
||||
g_all_objects.getData().erase(obj);
|
||||
g_all_objects.unlock();
|
||||
//delete obj;
|
||||
} // removeObject
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Checks if any objects are still allocated, and if so print information
|
||||
* about those objects. */
|
||||
void checkForLeaks()
|
||||
{
|
||||
std::cout << "checking for leaks... " << std::endl;
|
||||
|
||||
if (g_all_objs.size()>0)
|
||||
g_all_objects.lock();
|
||||
if (g_all_objects.getData().size()>0)
|
||||
{
|
||||
std::cout << "leaks detected!!" << std::endl;
|
||||
std::cout << "\n\n* * * * WARNING * * * * WARNING * * * * MEMORY LEAK! * * * *\n" << std::endl;
|
||||
std::cout << "\n\n* * * * WARNING * * * * WARNING * * * * "
|
||||
"MEMORY LEAK! * * * *\n" << std::endl;
|
||||
std::cout << "LEAK CHECK: " << g_all_objects.getData().size()
|
||||
<< " watched objects leaking" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "ok (no watched class left leaking)" << std::endl;
|
||||
return;
|
||||
}
|
||||
std::cout << "LEAK CHECK: " << g_all_objs.size() << " watched objects leaking" << std::endl;
|
||||
|
||||
std::set<MyObject*>::iterator it;
|
||||
for (it = g_all_objs.begin(); it != g_all_objs.end(); ++it)
|
||||
std::set<AllocatedObject*>::iterator it;
|
||||
for (it = g_all_objects.getData().begin();
|
||||
it != g_all_objects.getData().end(); ++it)
|
||||
{
|
||||
(*it)->print();
|
||||
}
|
||||
/*
|
||||
for (int n=0; n<g_all_objs.size(); n++)
|
||||
{
|
||||
g_all_objs[n].print();
|
||||
}*/
|
||||
}
|
||||
g_all_objects.unlock();
|
||||
} // checkForLeaks
|
||||
|
||||
}
|
||||
} // namespace MemoryLeaks
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
/*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2011-2012 Marianne Gagnon, Joerg Henrichs
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
|
||||
#ifndef __LEAK_CHECK_H__
|
||||
#define __LEAK_CHECK_H__
|
||||
#ifndef HEADER_LEAK_CHECK_HPP
|
||||
#define HEADER_LEAK_CHECK_HPP
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
@@ -24,57 +26,30 @@
|
||||
|
||||
namespace MemoryLeaks
|
||||
{
|
||||
|
||||
class AbstractLeakCheck;
|
||||
|
||||
class MyObject
|
||||
{
|
||||
char** stack;
|
||||
int stackSize;
|
||||
public:
|
||||
AbstractLeakCheck* obj;
|
||||
|
||||
MyObject(AbstractLeakCheck* obj);
|
||||
void print();
|
||||
};
|
||||
|
||||
class AllocatedObject
|
||||
{
|
||||
/** Keep stack information if available (OSX only). */
|
||||
char **m_stack;
|
||||
/** Keeps stacksize information if available (OSX only). */
|
||||
int m_stack_size;
|
||||
public:
|
||||
AllocatedObject();
|
||||
virtual ~AllocatedObject();
|
||||
virtual void print() const;
|
||||
}; // AllocatedObjects
|
||||
|
||||
// ========================================================================
|
||||
void checkForLeaks();
|
||||
|
||||
void addObj(MyObject* obj);
|
||||
void removeObj(MyObject* obj);
|
||||
void addObject(AllocatedObject* obj);
|
||||
void removeObject(AllocatedObject* obj);
|
||||
|
||||
class AbstractLeakCheck
|
||||
{
|
||||
MyObject* m_object;
|
||||
|
||||
public:
|
||||
|
||||
AbstractLeakCheck()
|
||||
{
|
||||
m_object = new MyObject( this );
|
||||
addObj( m_object );
|
||||
}
|
||||
|
||||
AbstractLeakCheck(const AbstractLeakCheck &t)
|
||||
{
|
||||
m_object = new MyObject( this );
|
||||
addObj( m_object );
|
||||
}
|
||||
|
||||
virtual ~AbstractLeakCheck()
|
||||
{
|
||||
removeObj( m_object );
|
||||
}
|
||||
|
||||
virtual void print() const
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace MemoryLeaks
|
||||
|
||||
#define LEAK_CHECK() \
|
||||
class LeakCheck : public MemoryLeaks::AbstractLeakCheck\
|
||||
class LeakCheck : public MemoryLeaks::AllocatedObject\
|
||||
{ public:\
|
||||
virtual void print() const\
|
||||
{ \
|
||||
|
||||
Reference in New Issue
Block a user