Reputation: 666
Recently I have encountered the error double free or corruption error in my project. After some test runs , the problem is pinned down to the copy function which uses memcpy.
class Pen
{ string make;
string model;
string color;
public:
Pen();
}
class A
{ private:
Pen* array; //an array that stores pen objects
int NumOfItem;
int Maxsize;
void CopyArray(const A& source);
public:
A();
A(const A& source);//copy constructor where uses the CopyArray private mentioned below
~A();
}
void A::CopyArray(const A& source)
{
memcpy(array, source.array, len * sizeof(Pen));//
return;
}
void A::A(const A& source)//copy constructor that performs a deep copy from B
{ array = new Pen[source.NumOfItem];
NumOfItem = source.NumOfItem;
MaxisIze=source.Maxize;
CopyArray(source);
}
When I change my code and use for loop to copy each parameter, it works. I am still trying to understand why memcpy is causing the problem if all it does is copying all the data bitwise to the new object......(Sorry for the messy format..)
Upvotes: 5
Views: 7349
Reputation: 81926
You can only use memcpy()
to copy objects that are trivially copyable. Let's see if Pen
meets this requirement.
#include <string>
using namespace std;
class Pen {
string make;
string model;
string color;
public:
Pen();
};
static_assert(std::is_trivially_copyable<Pen>::value, "Pen is not trivially copyable");
When compiled, this will return the error:
blah.cc:12:1: error: static_assert failed "Pen is not trivially copyable"
static_assert(std::is_trivially_copyable<Pen>::value, "Pen is not trivially copyable");
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
So, we can clearly see that Pen
is not trivially copyable, so we can't use memcpy()
with it. You should probably use std::copy
instead.
Upvotes: 8
Reputation: 726509
The problem with using memcpy
is that it bypasses copy constructors. This is OK only when your class is composed of primitives.
However, Pen
class has non-primitive data members of type std::string
. These objects require a call of copy constructor to be copied. memcpy
does not perform any calls to copy constructors, which leads to internal representations of std::string
becoming shared, which in turn causes undefined behavior on destruction.
Copying with a loop, on the other hand, invokes a copy constructor, so your code runs without a problem.
C++ Standard Library provides a utility function for copying ranges called std::copy
. Using this function avoids the problem that you see, because it invokes copy constructors as needed.
Upvotes: 13