2

How do i dynamically allocate memory inside a class?

To clearify my question i made up an example. I would construct an instance a of A and copy it into b. After usage a and b would be destructed and the allocated memory would be freed twice in the destructor.

So how would i handle this situation?

#include <stdlib.h>

class A {
public:
    char * allocatedMemory;
    A(int length) {
        allocatedMemory = (char *) malloc(sizeof(char) * length);
    }

    ~A(){
        free(allocatedMemory);
    }
};

int main() {
    A a = A(50);
    A b = a;
    return 0;
}

PS: To understand the Context: I am trying to figure out by example how std::string allocates and frees memory. Only the basic allocation of course.

nvoigt
  • 75,013
  • 26
  • 93
  • 142
har0ke
  • 98
  • 1
  • 8
  • 4
    Search for "the rule of three" (and "five" and "zero"). – molbdnilo Sep 13 '16 at 09:43
  • Have you considered overloading the assignment operator? – Adrian Jałoszewski Sep 13 '16 at 09:43
  • 1
    Hi the problem you are facing is due to shallow copy. If you wont provide the copy constuctor explicitly then the default copy constructor will be provided by compiler to inialize one object using exising object. The default copy constructor does the bit wise copying. I.e. just copy the address stored in pointer of one object to another. To avoid such double free problem, you need to do deep copy. Write your own copy constructor, inside that copy constructor explicitly allocate memory for your character pointer using new then using memcpy() copy the actual content. Hope this will help. – sagar Sep 13 '16 at 09:50
  • Thanks guys. The copy constructor was all i needed! – har0ke Sep 13 '16 at 09:54
  • Hi if my comment solved your problem. Will you please accept my answer and vote my comment. Thanks. – sagar Sep 13 '16 at 10:01
  • 1
    Why not just use something that already has the semantics you want, like `std::vector`? – David Schwartz Sep 14 '16 at 03:56
  • As described, i designed an example for clarification purposes. So mostly for gathering knowledge on how this could be done in background, which could be useful for more complex situations. – har0ke Sep 14 '16 at 22:05

1 Answers1

4

Hi the problem you are facing is due to shallow copy. If you wont provide the copy constuctor explicitly then the default copy constructor will be provided by compiler to inialize one object using exising object. The default copy constructor does the bit wise copying. I.e. just copy the address stored in pointer of one object to another. To avoid such double free problem, you need to do deep copy. Write your own copy constructor, inside that copy constructor explicitly allocate memory for your character pointer using new then using memcpy() copy the actual content. Hope this will help.

 #include <stdlib.h>
 class A 
 {
    public:
    char * allocatedMemory;
    int length;
    A(int length):length(length) 
    {
          // i am ignoring exception due to failure in new to keep code simple
          this->allocatedMemory = new char[length];
    }
    A(const A& obj)
    {
        this->allocatedMemory = new char[obj.length];
        memcpy(this->allocatedMemory, obj.allocatedMemory, obj.length);
        this->length = obj.length;

    }
    A& operator=(const A& obj)
    {
         if(this != &obj)
         {
             if(this->length == obj.length)
             {
                 memcpy(this->allocatedMemory, obj.memory, obj.length);
             }
             else
             {
                 delete[] this->allocatedMemory;
                 this->allocatedMemory = NULL;
                 this->allocatedMemory = new char[obj.length];
                 memcpy(this->alocatedMemory, obj.allocatedMemory, obj.length);
                 this->length = obj.length;
             }
        }
        return *this;
     }


    ~A()
   {
        if(allocatedMemory)
            delete[] allocatedMemory;
   }
};

int main() 
{
    A a = A(50);
    A b = a;
    return 0;
}
sagar
  • 367
  • 2
  • 12
  • 1
    `memcpy` needs a length parameter, and the `operator=` has a lot of mistakes. For getting started I'd suggest using copy-and-swap for `operator=`. – M.M Sep 13 '16 at 10:38
  • 1
    `if(allocatedMemory)` is redundant, it is safe to `delete` a null pointer. Also you are correctly handling allocation failure in the constructor -- it's good practice for the constructor to throw when it was unable to create an object – M.M Sep 13 '16 at 10:39
  • @M.M hi thanks for the coments. Will you please let me know what are the mistakes in operator= here. I will improve those errors. – sagar Sep 13 '16 at 20:50
  • 1
    Start again, and think about what you are doing. You forgot to set both the length and the allocated sinze in the current object. See [what is the copy and swap algorithm](http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom) – M.M Sep 13 '16 at 23:55
  • @M.M yes i missed to inirialize length in current object.Edited the answer. – sagar Sep 14 '16 at 03:55
  • 1
    You still fail to handle the case of `obj.length > length` – M.M Sep 14 '16 at 03:59
  • Actually i assumed that identical objects where lentgh represents the amount of memory to be allocated. But you are right the length case issue still exists here. – sagar Sep 14 '16 at 04:11