Byng Byng - 9 days ago 5
C++ Question

constructor not being called and "pointer being freed was not allocated" error

I've started picking up C++. The concepts are hard since I don't have any prior object-oriented programming experience. I am learning built-in arrays and constructors/destructors, and I have encountered an error that I cannot wrap my head around. Here, I'll show you guys the code.

The class definition goes

class arraysClass{

public:

int size1;
int size2;

int **frequencies;

arraysClass(int size1, int size2){
cout << "Constructor: size1&size2 " << size1 << " " << size2 << endl;
frequencies = new int*[size1+1];
for (int i=0; i<=size1; i++){
frequencies[i] = new int[size2+1];
}
}

//Destructor
~arraysClass()
{
cout << "Destructor: size1&size2 " << size1 << " " << size2 << endl;
for (int i=0; i<=size1; i++){
delete [] frequencies[i];
}
delete [] frequencies;

}
};


and here is my main function

int main()
{
int size1 = 20;
int size2 = 30;
arraysClass arrays1(size1, size2);

arraysClass arrays2 = arrays1;

arrays2.size1 = size1;
arrays2.size2 = size2;

return 1;
}


What I get as the result is


Constructor: size1&size2 20 30

Destructor: size1&size2 20 30

Destructor: size1&size2 0 0

a.out(41138,0x7fff75694000) malloc: *** error for object 0x7fa2eac032d0: pointer being freed was not allocated


The weird thing is that the constructor was only called once, when there is clearly a second instance of my class object. I have not made any copy constructors or overloaded the operator= function, so I'm not really sure what to make of this situation.

Anyone care to help a hopeless college student? Thanks!

Answer

arraysClass arrays2 = arrays1; Here default copy constructor was invoked and member int **frequencies was copied to arrays2. The catch is - this is so called, shallow copy, i.e. only pointer value is copied and both pointers pointing to same memory.

At the end of main function, both arrays1 and arrays2 are destroyed, and in destructor, int **frequencies (remember, they are pointing to same location) deleted twice. And so, first delete is going fine, second one is crashing program, because deleting already deleted pointer is undefined behavior.

Correct fix here is to make deep copy in copy constructor and overloaded operator=. Example with copy constructor:

arraysClass(const arraysClass& rhs) {
    cout << "Copy Constructor" << endl;
    size1 = rhs.size1;
    size2 = rhs.size2;
    frequencies = new int*[size1+1];
    for (int i=0; i<=size1; i++){
        frequencies[i] = new int[size2 + 1];
        memcpy(frequences[i], rhs.frequences[i], rhs.size2 + 1)
    }
}