new operator overwriting an existing object
- by dvpdiner2
I have a custom FastStack class, implemented as a fixed size array and an index into that array.
In my copy constructor, I allocate the array and then assign each object from the copy's array into the new array. There's some refcounting in the objects on the stack, hence assignment is used rather than a simple copy.
The problem is that when allocating the array, it sometimes overwrites part of the other stack's array. As can be expected, this leads to eventual segmentation faults when that data is dereferenced.
class FastStack {
private:
int m_size, m_ptr;
ObjectRef* m_stack;
public:
FastStack(int size) : m_size(size), m_ptr(-1) {
m_stack = new ObjectRef[m_size];
}
FastStack(const FastStack& copy) : m_size(copy.m_size), m_ptr(copy.m_ptr) {
long a = (long)copy.m_stack[0];
m_stack = new ObjectRef[m_size];
if ((long)copy.m_stack[0] != a)
fprintf(stderr, "\nWe have a serious problem!\n\n");
for (int i = 0; i <= m_ptr; i++)
m_stack[i] = copy.m_stack[i];
}
~FastStack() {
delete[] m_stack;
}
};
class ObjectRef {
private:
DataObj* m_obj;
public:
ObjectRef() : m_obj(0) { }
ObjectRef(DataObj* obj) : m_obj(obj) {
if (m_obj) m_obj->addRef();
}
ObjectRef(const ObjectRef& obj) : m_obj(obj.m_obj) {
if (m_obj) m_obj->addRef();
}
~ObjectRef() {
if (m_obj) m_obj->delRef();
}
ObjectRef& operator=(DataObj* obj) {
if (obj) obj->addRef();
if (m_obj) m_obj->delRef();
m_obj = obj;
return *this;
}
ObjectRef& operator=(const ObjectRef& obj) {
if (obj.m_obj) obj.m_obj->addRef();
if (m_obj) m_obj->delRef();
m_obj = obj.m_obj;
return *this;
}
};
I see that "We have a serious problem!" line shortly before a segfault, and stepping through it with gdb I can see that one of the ObjectRefs created by new has the same address as the other stack's array.
My first instinct is to say that new should never be allocating memory that is already in use, but that clearly seems to be the case here and I am at a complete loss as to what can be done.
Added: At the time that I see this happen, m_size = 2 and m_ptr = 0.