GalaxyVintage
GalaxyVintage

Reputation: 666

Using memcpy to copy an array of objects

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

Answers (2)

Bill Lynch
Bill Lynch

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

Sergey Kalinichenko
Sergey Kalinichenko

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

Related Questions