Reputation: 18918
I have a class Foo
defined like this:
class Foo
{
public:
Foo(int num);
Foo(const Foo& other);
~Foo();
Foo& operator=(const Foo& other);
...
private:
string *fooArray;
void clearMemory();
...
}
Foo::Foo(int num)
{
fooArray = new string[num];
}
Foo::Foo(const Foo& other)
{
*this = other;
}
Foo::~Foo()
{
clearMemory();
}
Foo& operator=(const Foo& other)
{
clearMemory();
fooArray = new string[other.size]; // size is a private variable
memcpy(fooArray, other.fooArray, other.size * sizeof(string));
}
void Foo::someOtherFooFuncion(int newNum)
{
clearMemory(); // crash with Visual Studio, does not crash with g++, but g++ also
// crashes when destructor is called
fooArray = new string[newNum];
}
void Foo::clearMemory()
{
if(fooArray != NULL)
{
delete[] fooArray; // sometimes it crashes here with g++; it always crashes when
// compiling in Visual Studio
fooArray = NULL;
}
}
As noted in the code comments, it is giving me crashes at times. I have tried following the steps in GDB, I got as far as
destructing Foo:
@0x7fff5fbff9b0
$26 = {
fooArray = 0x1001009d8,
...
}
And then delete[] fooArray
is reached, and all of a sudden
Foo(49858) malloc: *** error for object 0x100100990: pointer being freed was not allocated
Have no idea where the 0x100100990 came from.
I realize the code is very incomplete, but I really don't know even where to start hunting for the bug right now, and would like some tips as to what possible conditions could cause delete[]
errors.
EDIT:
Added c'tor, d'tor, and assignment operator. I am away from PC so code may not be 100% accurate. Assigning values to fooArray and accessing them works just fine though.
Also, I would greatly appreciate a general list of problems that could potentially cause delete[]
to throw an error, so that I could at least have some idea of where to look in the code.
EDIT 2:
So I followed Xeo's advice to use std::uninitialized_copy
, now the code works fine and compiles under g++. The destructor works fine in Visual Studio as well, but somehow deleting fooArray in someOtherFooFuncion
makes it crash.
Any other ideas?
Upvotes: 1
Views: 684
Reputation: 500773
Make sure you define a copy constructor and an assignment operator. They will need to allocate memory for fooArray
. If you don't define the copy ctor and operator=
, the compiler will generate them for you. However, the compiler-generated ones will just copy the fooArray
pointer, potentially resulting in double deletes
.
If you are defining them already, please add the relevant code to your question.
edit: I can see that your copy constructor is not allocating memory, and your assignment operator is using memcpy()
. Both can cause problems.
Upvotes: 2
Reputation: 131837
I can't stress that point enough. When memcpy
ing a class object in C++ (non-POD to be exact), you're breaking that class' invariants defined by its constructors, since you are circumventing exactly those. Every time you memcpy
a a std::string
class, you get a new object referring to the same memory as another object. You'll get a double delete with this, which is causing your crash.
Use std::uninitialized_copy
from <algorithm>
like this:
// src_begin src_end dest
std::uninitialized_copy(other.array, other.array + other.size, array);
(untested because I'm writing this from my iPod)
Or even better, just use std::vector
instead of raw memory. You'll have no need for a destructor and copy ctor / assignment operator anymore.
Upvotes: 1
Reputation: 122001
If you define a default constructor you must initialise fooArray
to NULL, otherwise fooArray
could be pointing to a random memory location which is then subject to a delete[]
.
Upvotes: 1