C++, copy constructor confusion - c++

say I created a custom Array class and have following constructor:
Array::Array(size_t size)
{
mySize = size;
//myData is of type int*
myData = new int[mySize]; // this stuff is allocated on a heap
}
To my knowledge, a default copy constructor in this case would be implemented like that:
Array::Array(Array& a)
{
mySize = a.mySize;
myData = a.myData; //points to the same memory on the heap
}
Finally, say I have following code in my main.cpp file
int main()
{
Array a(1);
Array b(a); //copy constructor is invoked
}
What I expected to be was a memory leak due to deletion of myData pointers to the free store memory, BUT I have following runtime error :
*** glibc detected *** ./main.out: double free or corruption (fasttop): 0x086ad008 ***
WHY? It seems that ~Array() somehow auto frees memory allocated on a heap - but this is very counter intuitive to me. Maybe I am missing something?
UPDATE:
class Array{
private:
size_t mySize;
int *myData;
...
UPDATE 2:
main.cpp:
#include <iostream>
#include "array.h"
int main()
{
Array a(1);
Array b(a);
}
array.h:
#ifndef ARRAY_H_
#define ARRAY_H_
#include <stddef.h>
class Array{
private:
size_t mySize;
int *myData;
public:
Array(size_t size);
~Array();
void set(int i,int val);
int get(int i);
size_t getSize();
};
#endif
array.cpp:
#include "array.h"
Array::Array(size_t size)
{
mySize = size;
myData = new int[mySize];
}
Array::~Array()
{
delete[] myData;
}
void Array::set(int i, int val)
{
if(i>=0 && i<mySize)
myData[i] = val;
}
int Array::get(int i)
{
if(i>=0 && i<mySize)
return myData[i];
else return -1;
}
size_t Array::getSize()
{
return mySize;
}

I think in your destructor you have
Array::~Array(void)
{
delete [] myData; //points to the same memory on the heap
}
The problem is double free
Example:
int main()
{
Array a(1); // here a.myData = 0x12345678
Array b(a); //copy constructor is invoked // here b.myData = 0x12345678
// pop stack (call destroy of object)
// delete b.myData
// delete a.myData already delete
}
Double free
EDIT:
For your copy contructor use const because you don't modify a.
Array::Array(const Array& a)
{
mySize = a.mySize;
myData = a.myData; //points to the same memory on the heap
}
Good Luck !

So... despite your claims, it turns out you do delete the array in the destructor, and the copy constructor is a shallow copy, so you get a double delete. Simple.
Array::~Array()
{
delete[] myData;
}
Since this is a dynamic array, it should own the data, therefore you are right to delete in the destructor, but you need to "deep" copy in the copy constructor and the assignment operator. See the rule of three.

Your copy is a shallow copy, so IF you have a destructor that frees memory, each object attempts to delete the same memory.
You don't have to do a shallow copy. You could write your own explicit copy constructor that copies the actual data into a newly allocated array.
I like Google's suggestion to disable copy and assignment constructors and prefer explicit CopyFrom() methods.

"double free" means that the same pointer has been given to delete[] twice. because in your destructor (presumably) it's delete[]-ed both in object a and b. practical solution: use std::vector, don’t mess with raw arrays etc. needlessly.

I think your desctructors (from array 'a' and 'b') are trying to free the same memory (double free). Maybe you should check you myData before freeing.

Related

How to delete dynamic allocated array in c++?

I got stuck with deleting an dynamically allocated array of int.
I've got a destructor, where I'm trying to use a loop for to delete all elements of array and finally delete it.
I have code on http://rextester.com/OTPPRQ8349
Thanks!
class MyClass
{
public:
int _a;
int* c;
int fRozmiar;
static int fIlosc;
MyClass() //default constructor
{
_a=0;
c = new int [9];
for(int i = 0; i<=9; i++)
{
c[i] = 1;
}
fIlosc++;
}
MyClass(int a1, int c1) // parametrized constructor
{
_a=a1;
c = new int [c1];
for(int i = 0; i<=c1; i++)
{
c[i] = rand();
}
fIlosc++;
}
MyClass(const MyClass &p2) // copy constructor
{
_a =p2._a;
c = p2.c;
fRozmiar = p2.fRozmiar;
fIlosc = fIlosc;
fIlosc++;
}
~MyClass(); // destructor
static int getCount() {
return fIlosc;
}
};
//Initialize static member of class
int MyClass::fIlosc = 0;
MyClass::~MyClass()
{
for(int i = 0; i<sizeof(c); ++i)
{
delete[] c[i];
}
delete[] c;
fIlosc--;
}
int main()
{
}
Remove the for-loop, but keep the delete[] c after it.
Each int doesn't need to be deleted because they're not dynamically allocated. If you needed to delete them, then the for-loop wouldn't work becuase: sizeof(c) is not the size of the array, and delete[] should have been delete instead.
There are several problems in the code.
First, that loop in the destructor must go. If you didn’t new it, don’t delete it.
Second, a loop through an array of N elements should be for (int i = 0; i < N; ++i). Note that the test is i < N, not i <= N. The loops as currently written go off the end of the array. That’s not good.
Third, the copy constructor copies the pointer. When the first object goes out of scope its destructor deletes the array; when the copy goes out of scope its destructor also deletes the array. Again, not good. The copy constructor has to make a copy of the array. In order to do that the class needs to also store the number of elements the array.

Program Crashing at Destructor

I can't seem to understand why my program runs successfully and then crashes at destructor. Below is my main() source code (which is fairly simple, it sends an array of 5 variables to a class template which creates the appropriate type. I did some research and seem to be missing something that might cause a crash because of an additional call of the destructor? I'm a little fuzzled and it's most likely a simple fix.
main.cpp:
int main()
{
// using integer data type
int arraya[5] = { 1, 2, 3, 4, 5 };
GenericArray<int> a(arraya, 5);
a.print();
// using float data type
float arrayb[5] = { 1.012, 2.324, 3.141, 4.221, 5.327 };
GenericArray<float> b(arrayb, 5);
b.print();
// using string data type
string arrayc[] = { "Ch1", "Ch2", "Ch3", "Ch4", "Ch5" };
GenericArray<string> c(arrayc, 5);
c.print();
return 0;
}
header file contents:
#ifndef GENERIC_ARRAY_H
#define GENERIC_ARRAY_H
#include<string>
#include<iostream>
template<typename type>
class GenericArray
{
public:
GenericArray(type array[], int arraySize); // constructor
~GenericArray(); // destructor
void print(); // the print function
GenericArray(const GenericArray &obj); //copy constructor
private:
type *ptr; //new pointer of respective type
int size;
};
template<typename type>//print() function
void GenericArray<type>::print()
{
for (int index = 0; index < size; index++)
{
cout << ptr[index] << " ";
}
cout << endl;
}
template<typename type>//Constructor
GenericArray<type>::GenericArray(type array[], int arraySize)
{
size = arraySize;
ptr = new type[size];
ptr = array;
}
template<typename type>//Destructor
GenericArray<type>::~GenericArray()
{
cout << "Freeing Memory!";
delete[] ptr;
}
template<typename type>//Copy Constructor
GenericArray<type>::GenericArray(const GenericArray &obj)
{
*ptr = *obj.ptr;
}
#endif
-In the print() method:
It isn't safe, that there was memory allocated at memory positions ptr ... (ptr + size - 1), so you might run into a segmentation fault.
-In the constructor:
you allocate memory via new, but then immediately redirect your pointer to point at the same position as array is pointing at. . This means you got a memory leak.
-In the destructor:
As was already mentioned, your program crashes here when the destructor is called, because the delete[] doesn't operate on the memory that was allocated with new, see the constructor remarks.
-In the copy constructor:
There are two problems here. First of all, you can't dereference the lhs-ptr here because there wasn't memory allocated for him. Moreover, if there was memory allocated for ptr, the statement *ptr = *obj.ptr; would just copy the first element of obj.ptr (if there was memory allocated at this position as well) to the first element of ptr.`
The constructors are defined incorrectly. They shall copy elements of source objects.
For example
#include <algorithm>
//...
template<typename type>//Constructor
GenericArray<type>::GenericArray( const type array[], int arraySize )
: ptr( new type[arraySize] ), size( arraySize )
{
std::copy( array, array + arraySize, ptr );
}
template<typename type>//Copy Constructor
GenericArray<type>::GenericArray( const GenericArray &obj )
: ptr( new type[obj.size] ), size( obj.size ),
{
std::copy( obj.ptr, obj.ptr + arraySize, ptr );
}
Also you need to define the copy assignment operator.

How to realloc in c++?

The following code constitutes a MCVE, this reproduces the problem I want to ask about but it's not the real code. The real code is quite more complicated so that's why I wrote this for a demonstration of the problem.
The key feature I am looking for is to be able to grow a dynamically allocated array, please do not suggest using the stl because it's explicitly forbidden. This code is for educational purpose and thus there are restrictions.
#include <cstring>
#include <iostream>
class Value
{
public:
Value(int value = 0);
Value(const Value &value);
Value &operator =(const Value &other);
~Value();
operator int() {return *m_absurdPointer;}
private:
int *m_absurdPointer;
};
Value::Value(int value) :
m_absurdPointer(new int[1])
{
*m_absurdPointer = value;
}
Value::Value(const Value &value)
{
m_absurdPointer = new int[1];
memcpy(m_absurdPointer, value.m_absurdPointer, sizeof(*m_absurdPointer));
}
Value &Value::operator =(const Value &other)
{
m_absurdPointer = new int[1];
memcpy(m_absurdPointer, other.m_absurdPointer, sizeof(*m_absurdPointer));
return *this;
}
Value::~Value()
{
delete[] m_absurdPointer;
}
class ValueArray
{
public:
ValueArray();
~ValueArray();
void append(const Value &value);
void show() const;
private:
Value *m_array;
unsigned int m_capacity;
unsigned int m_length;
};
ValueArray::ValueArray() :
m_array(nullptr)
, m_capacity(0)
, m_length(0)
{
}
ValueArray::~ValueArray()
{
delete[] m_array;
}
void
ValueArray::append(const Value &value)
{
if (m_length >= m_capacity)
{
Value *newarray;
unsigned int unitSize;
unitSize = 1;
newarray = new Value[m_capacity + unitSize];
if ((m_capacity > 0) && (m_array != nullptr))
memcpy(newarray, m_array, m_capacity * sizeof(*m_array));
delete[] m_array;
m_array = newarray;
m_capacity += unitSize;
}
m_array[m_length++] = value;
}
void
ValueArray::show() const
{
for (size_t i = 0 ; i < m_length ; ++i)
std::cout << static_cast<int>(m_array[i]) << std::endl;
}
int
main(void)
{
ValueArray example;
for (int i = 0 ; i < 10 ; ++i)
example.append(Value(i));
example.show();
return 0;
}
It causes as you can see a double free issue, because the delete[] m_array; calls the destructor of the class Value after it has copied the values to the re-newed array.
I tried to do this with malloc()/realloc() but I need the destructor of Value() to be called so new is mandatory because I can't use free().
How to prevent this?, if I remove the delete[] m_absurdPointer; the double free would be gone of course but there would be a memory leak.
You basically want to implement an own vector class, right?
OK, first things first: As far as I know you cannot grow previously allocated memory. At least not with the standard allocator.
So you need to allocate a new, larger chunk of memory.
You can do this the standard way, using new:
Type * newdata = new Type[size];
In this case the constructor of the class Type will be called for each new element, which is size times.
To get your old data into that new array you need to copy or move it there:
for (size_t it = 0; it < oldsize; ++it) {
newdata[it] = olddata[it];
// newdata[it] = std::move(olddata[it]);
}
This is what std::copy resp. std::move are doing. (You could also use std::swap inside a loop.)
For that to work the Type class needs both a default constructor and a valid implementation of copy or move assignment.
You're using memcpy. In C++, this is generally a bad idea: Your implemented assignment operator isn't called, Therefore both the objects in your old array and the raw copies are using the same pointer, which is why you get that double free, obviously.
You could also allocate raw memory and use placement new to copy or move construct the new objects from the old ones:
void * memory = new char[size * sizeof(Type)];
for (size_t it = 0; it < oldsize; ++it) {
new (memory + it * sizeof(Type)) Type(olddata[it]); // copy
}
The above is only an example, for real code you need to consider alignment, too.
Finally, I'm sure you can somehow trick the default allocator to free your (old) memory without destructing the objects within, this allowing you to use the raw copy memcpy made. Though this would be a hack and could break on complex classes, it's not the C++ way of doing this.
The idiomatic way is to copy or move the old objects to the new storage (with either assignment or construction).
You should use the move-constructor if you have to stick with an vector-like implementation of ValueArray:
class Value
{
public:
Value(int value = 0);
Value(const Value &value);
Value(Value&& val);
Value &operator =(const Value &other);
Value &operator =(Value&& other);
~Value();
operator int() {return *m_absurdPointer;}
private:
int *m_absurdPointer;
};
Value::Value(Value&& o) : m_absurdPointer(o.m_absurdPointer) {
o.m_absurdPointer = nullptr;
}
Value &operator =(Value&& o) {
delete[] this->m_absurdPointer;
this->m_absurdPointer = o.m_absurdPointer;
o.m_absurdPointer = nullptr;
}
void
ValueArray::append(const Value &value)
{
if (m_length >= m_capacity)
{
Value *newarray;
unsigned int unitSize;
unitSize = 1;
newarray = new Value[m_capacity + unitSize];
if ((m_capacity > 0) && (m_array != nullptr)) {
std::move(m_array, m_array + m_length, newarray);
}
delete[] m_array;
m_array = newarray;
m_capacity += unitSize;
}
}

C++ vector of structs with pointers

I'm trying to create a vector of structs which each have a an array of pointers. However, I can't seem to delete the vector without a memory problem.
When I run valgrind
==29801== Invalid free() / delete / delete[] / realloc()
==29801== at 0x4A05A36: operator delete (vg_replace_malloc.c:515)
==29801== by 0x4009D4: test_struct::~test_struct() (in /home/hltcoe/rcotterell/code-switching/a.out)
==29801== by 0x40142B: void std::_Destroy(test_struct*) (in
/home/hltcoe/rcotterell/code-switching/a.out)
==29801== by 0x401299: void std::_Destroy_aux::__destroy(test_struct*,
test_struct*) (in /home/hltcoe/rcotterell/code-switching/a.out)
EDIT
#include <vector>
using namespace std;
struct test_struct {
public:
int * array;
test_struct() {
array = NULL;
}
~test_struct() {
delete[] array;
}
private:
test_struct(const test_struct& that);
test_struct& operator=(const test_struct& that);
};
int main(int argc, char ** argv) {
vector <test_struct> data;
for (int i = 0; i < 5; ++i) {
test_struct tmp;
tmp.array = new int[5];
data.push_back(tmp);
}
}
And it gives the following compile error. Any ideas?
You should follow rule of three or Use STL container where ever possible:
struct test_struct
{
explicit test_struct(int size) : array(size) { }
std::vector<int> array;
};
int main()
{
vector <test_struct> data(5, test_struct(5));
return 0;
}
Your solution doesn't work because of test_struct destructor and the fact you're trying to store your structs in a vector.
When test_struct tmp is pushed to the vector, a copy of test_struct is created. Then tmp is destroyed with calling delete[] array and the copy in vector <test_struct> data ends up with a dangling pointer.
You probably need to rethink your architecture, or at least add a copy constructor for the test_struct that will copy the whole array

Placement new for contiguous memory

I am facing some problems for using placement new for contiguous memory.Please guide me, if there is any other way to do this.
Please refer my code.
#include <new>
//================================================
class MyClass
{
private:
int ma;
public:
MyClass():ma(-1){}
};
//===========================================
int main()
{
// I am allocating the memory for holding 10 elements of MyClass on heap
void* pMyClass = ::operator new(sizeof(MyClass)*10);
//! Note :: the address of pMyClass1 and pMyClass will now point to same
//location after calling placement new
MyClass* pMyClass1 = :: new(pMyClass)MyClass();
//! Problem with this is that,
//! i can only instantiate the constructor for the base address. That is
//! pMyClass[0].
//! If i have to instantiate it for all the other instances,
//! that is pMyClass[1] to pMyClass[9], then how to do it ?
return 0;
}
You have the beginning of the memory in pMyClass, and the stride is sizeof(MyClass). So, what you need to do is for example:
MyClass* pMyClass2 = ::new((MyClass*)pMyClass + 1)MyClass();
Try:
MyClass* pMyClass1 = :: new(pMyClass)MyClass[10];
You have to call the placement new inside a loop that iterates on the 10 contiguous chunks of memory:
int main()
{
void* pMyClass = ::operator new(sizeof(MyClass)*10);
MyClass* pMyClass1 = reinterpret_cast<MyClass*>(pMyClass);
for (size_t i=0; i<10; ++i) {
::new(pMyClass1++)MyClass();
}
// ...
}