Original Post
I'm having a problem which seems to only occour in debug mode. I get an error (at runtime) about some heap error, and also says there is a bug in the program. I know/think that it has to do with that i'm either using freed memory, or freeing something twice. The code is based on the enguinity guides. When i get the error i get some info about a triggered breakpoint in xutility. The error is caused by MemoryObject::collectRemaining(). Or more specifically, the line "delete o" in that method. I seem to delete/free something which already is freed. Or, something is trying to free it afterwards. I'm not able to fix this problem though. The debugger tells me the problem happends in free.c at this line: This is not anything i've written. It's related to delete. In the following code, much has been stripped away. There are a few calls to functions such as getLength(), m_getAllocatedElements() and so, but i think their names explains what they does. Here are the (stripped) relevant code: main.cpp MemoryPointer.hpp - Full code Vector.hpp - Full code Collection.hpp - Full code MemoryObject.cpp - This is where it crashes - Full code Sorry for all that code, but i didn't want to miss anything, if the error were caused by something i didn't expect. [Edited by - claesson92 on January 20, 2010 2:14:36 AM]
retval = HeapFree(_crtheap, 0, pBlock);
#include "CGDK.hpp" //This includes Collection.hpp, MemoryObject.hpp, MemoryPointer.hpp and some standard C++ headers
using namespace std;
using namespace CGDK::core;
int main(int argc, char *argv[])
{
MemoryPointer<Vector<int>> m = new Vector<int>(25);
MemoryObject::collectRemaining();
return 0;
}
#include "_stdlibrary.hpp" //Includes some standard c++ headers and my own classes
//Class definition...
template<typename T>
CGDK::core::MemoryPointer<T>::MemoryPointer()
{
m_object = 0;
}
template<typename T>
CGDK::core::MemoryPointer<T>::MemoryPointer(T *obj)
{
m_object = 0;
*this = obj;
}
template<typename T>
CGDK::core::MemoryPointer<T>::~MemoryPointer()
{
if(m_object)
{
m_object->release();
}
}
template<typename T>
void CGDK::core::MemoryPointer<T>::operator=(T *obj)
{
//Decrement the reference counter if the is an object
if(m_object)
{
m_object->release();
}
m_object = obj;
//Increment the reference counter...
if(m_object)
{
m_object->addReference();
}
}
template<typename T>
T* CGDK::core::MemoryPointer<T>::operator->() const
{
CGDK_ASSERT(m_object != 0, "Tried to -> on a NULL smart pointer");
return m_object;
}
//Some includes
template<typename T>
class Vector : public CGDK::core::Collection<T>
{
//Some code
};
template<typename T>
void CGDK::core::Vector<T>::m_initVector(T initvalue)
{
m_maxSize = 0;
//Set the initial value of new elements
setInitialValue(initvalue);
}
template<typename T>
CGDK::core::Vector<T>::Vector() : CGDK::core::Collection<T>::Collection(10, 5)
{
m_initVector();
}
template<typename T>
CGDK::core::Vector<T>::Vector(unsigned int size, T initvalue) : CGDK::core::Collection<T>::Collection(size, 5)
{
m_initVector(initvalue);
}
template<typename T>
CGDK::core::Vector<T>::~Vector()
{
}
template<typename T>
void CGDK::core::Vector<T>::setMaximumSize(unsigned int max)
{
m_maxSize = max;
}
template<typename T>
unsigned int CGDK::core::Vector<T>::getMaximumSize()
{
return m_maxSize;
}
//Includes
template<typename T>
class Collection<T> : public CGDK::core::MemoryObject
{
//Some code...
};
template<typename T>
void CGDK::core::Collection<T>::m_realloc(unsigned long elements)
{
unsigned long _oldsize = m_allocatedElements;
try
{
m_memPointer = new T[elements];
m_allocatedElements = elements;
}
catch(std::bad_alloc e)
{
CGDK_THROW("Unable to (re)allocate memory");
}
for(unsigned long i = _oldsize; i < m_allocatedElements; i++)
{
set(i, m_initValue);
}
}
template<typename T>
void CGDK::core::Collection<T>::m_pushBack(T val)
{
if(m_getFreeElements() == 0)
{
//We need to allocate more memory
m_grow();
}
m_memPointer[m_usedElements] = val;
m_usedElements++;
}
template<typename T>
void CGDK::core::Collection<T>::m_init(unsigned long elements, unsigned int growth)
{
m_initValue = static_cast<T>(0);
m_growth = growth;
m_allocatedElements = elements;
m_usedElements = 0;
try
{
m_memPointer = new T[elements];
}
catch(std::bad_alloc e)
{
CGDK_THROW("Unable to allocate memory");
}
}
template<typename T>
CGDK::core::Collection<T>::Collection()
{
m_init(5, 5);
}
template<typename T>
CGDK::core::Collection<T>::Collection(unsigned long elements, unsigned int growth)
{
m_init(elements, growth);
}
template<typename T>
CGDK::core::Collection<T>::~Collection()
{
delete[] m_memPointer;
}
#include "MemoryObject.hpp" //Contains the class definition and some includes
#include "Error.hpp"
std::list<CGDK::core::MemoryObject*> CGDK::core::MemoryObject::m_liveObjects;
std::list<CGDK::core::MemoryObject*> CGDK::core::MemoryObject::m_deadObjects;
void CGDK::core::MemoryObject::addReference()
{
++m_referenceCount;
}
void CGDK::core::MemoryObject::release()
{
--m_referenceCount;
if(m_referenceCount <= 0)
{
m_liveObjects.remove(this);
m_deadObjects.push_back(this);
}
}
CGDK::core::MemoryObject::MemoryObject()
{
m_liveObjects.push_back(this);
//m_listPosition = static_cast<unsigned long>(m_liveObjects.size()) - 1;
//Set the initial reference count to 0
m_referenceCount = 0;
}
CGDK::core::MemoryObject::~MemoryObject()
{
}
void CGDK::core::MemoryObject::collectGarbage()
{
for(std::list<MemoryObject*>::iterator it = m_deadObjects.begin(); it != m_deadObjects.end(); it++)
{
MemoryObject *o = (*it);
delete(o);
it++;
}
m_deadObjects.clear();
}
void CGDK::core::MemoryObject::collectRemaining()
{
collectGarbage();
for(std::list<MemoryObject*>::iterator it = m_liveObjects.begin(); it != m_liveObjects.end(); it++)
{
CGDK::core::MemoryObject *o=(*it);
delete o; ///////// <-- This is where it crashes
}
m_liveObjects.clear();
}