I have a Double free or corruption (fasttop) error on this code.
I think i missed something on the "copy constructor".
class Vector{
int taille;
int* ptr;
public:
Vector():taille(0), ptr(NULL){
...
}
Vector(int n){
...
}
//The most important one
Vector(const Vector& source){
if(source.ptr != NULL){
taille = source.taille;
ptr = new int[taille];
for(int i=0;i<taille;i++) ptr[i]=source.ptr[i];
}else{
taille=0;
ptr=NULL;
}
cout << "Copy constructor" << endl;
}
~Vector(){
if(ptr!=NULL) delete ptr;
}
};
And here's the test :
int main()
{
Vector b(5);
Vector a(b);
a=Vector(12);
return 0;
}
The above = operator does not call the copy constructor. Why ?
It says : "double free or corruption (fasttop)"
With the expression
a = Vector(12)
a few things are happening:
First a new temporary Vector object is created (from Vector(12)). This is constructed using the Vector(int) constructor.
The temporary object is assigned to a, using a.operator=(<temporary object>).
The default compiler-generated operator= function does a simple member-wise assignment, i.e. it basically does ptr = other.ptr. This means you now have two objects ptr members pointing to the same memory: The temporary object, and a.
The temporary object is destructed once the assignment is made. This means the memory occupied by that object is passed to delete (which really should be delete[]).
This of course means that a.ptr is no longer pointing to valid memory, and when it later goes out of scope and is destructed you try to delete the already deleted memory.
There is no copy-construction going on here. It's all copy-assignment. Copy construction is only used on actual construction, when an object is created (temporary or not). I think you're confused because the = symbol can be used for copy-construction, as in
Vector a = b; // This is a copy-construction
// The copy-constructor of `a` is called with
// a reference to `b` as argument
// It's equal to `Vector a(b)`
This is very different from assignment
a = b; // This is a plain assignment
// It is equal to `a.operator=(b)`
The crash is solved by following one of the rules of three, five or zero.
I also recommend you read e.g. this canonical assignment operator reference.
You are creating a temporary Vector in the assignment a = Vector(12), which is being assigned via operator= to a. The temporary Vector gets destroyed at the end of the assignment statement, and a gets destroyed at the end of the function. Both point at the same allocated array because you did not define a copy-assignment operator=:
http://www.cplusplus.com/doc/tutorial/operators/
Related
Can anyone explain the meaning of *p=*q in this C++ code? Is this a copy constructor concept?
class A{
//any code
}
int main(){
A *p=new A();
A *q=new A();
*p=*q;
return 0;
}
Is this a copy constructor concept?
No, what you are referring to is a copy assignment concept. Consider this:
int* p = new int{9};
int* q = new int{10};
*p = *q;
As you can see above, only the value of the variable q which is pointed to is copied. This is the equivalent of the copy assignment for objects. If you were to do this:
p = q;
Then this would not be a copy assignment, because both int's point to the same address and value, meaning any change to p or q would be reflected on the other variable.
To give a more concrete and validated example, here is some code:
int main()
{
int* p = new int{9};
int* q = new int{10};
*p = *q;
//p = 10, q = 10
*p = 11;
//p = 11, q = 10
delete p;
delete q;
}
And here is a supplementary counter-example
int main()
{
int* p = new int{9};
int* q = new int{10};
p = q;
//p = 10, q = 10
*p = 11;
//p = 11, q = 11
delete p;
//delete q; Not needed because p and q point to same int
}
As you can see, the changes are reflected on both variables for p=q
Side Note
You mentioned copy-construction, but you were unclear about the concept. Here is what copy-construction would have looked like:
int* p = new int{9};
int* q = new int{*p}; //q=9
Copy construction differs from copy assignment in the sense that with copy construction, the variable doesn't already have a value, and for an object, the constructor has yet to be called. Mixing up the 2 terms is common, but the fundamental differences make the two concepts, well, different.
It looks like, you're unclear about the copy constructor and copy assignment. Let's first have a look at both concepts individually, and then I'll come to your question. The answer is a little long, so be patient :)
Copy Constructor
Here, I'm not going to explain how to write a copy constructor, but when the copy constructor is called and when it's not. (If you want to know, how to write a copy constructor, see this)
A copy constructor is a special constructor for creating a new object as a copy of an existing object. (It is called whenever there's a need for making a copy of an existing object)
These are the scenarios when the copy constructor will be called to make the copy of an existing object:
Initializing an object with some previously created object:
SomeClass obj;
// ...
SomeClass anotherObj = obj; // here copy constructor will be called.
See, SomeClass obj; statement is simply creating an object (here, default constructor will be called to create the object). The second statement SomeClass anotherObj = obj; is instantiating an object, initialized with the values of obj (an existing object), so copy constructor will be called here. You can also initialize an object with an existing object this way: SomeClass anotherObj(obj); (This statement is equivalent to SomeClass anotherObj = obj;)
Except:
If you initialize with some rvalue expression. e.g.
SomeClass someObject = aObject + anotherObject;
In this case, move constructor will be called. See, What are move semantics?
Passing an object by value to some function (see Passing arguments by value):
See, the following code snippet, here the function doSomething is accepting an object as parameter by value:
void doSomething(SomeClass someObject)
{
// ...
}
There are some cases, when there will be a need to make the copy of the passed argument in the parameter object someObject, I've listed when there will be a need to make the copy and when there'll not be a need.
Have a look at the following code snippet:
SomeClass someObject;
// ...
doSomething(someObject); // here copy constructor will be called.
The statement SomeClass someObject; is just instantiating someObject by calling the default constructor.
The second statement doSomething(someObject); is calling the function doSomething previously shown, by passing someObject as argument. This is the case, when there's a need to make a copy of someObject to pass to the function.
Except:
Similiary, If we call doSomething with some rvalue expression, it will call move constructor instead of copy constructor.
Returning an object from a function by value:
Let's have a look at the following definition of doSomething
SomeClass doSomehing()
{
SomeClass someObject;
// ...
return someObject;
}
In the above function doSomething, an object of SomeClass is being created and after doing some task, the object is being returned by the function, in this case, a copy of the someObject will be created and returned.
Except:
Similiary, If doSomething returns some rvalue expression, it will call move constructor instead of copy constructor.
Copy Assignment
Copy Assignment is usually confused with the copy construction, let's have a look at how it is different than the copy construction:
SomeClass someObject;
// ...
SomeClass anotherObject;
// ...
anotherObject = someObject; // here copy assignment operator will be called.
The first two statements are just creating someObject and anotherObject, you see, the third statement is actually calling the copy assignment operator and not the copy constructor.
Constructors are only called when some new object is being created. And in the case of anotherObject = someObject;, both the objects are already created, so there won't be any call to the copy constructor. Instead a copy assignment operator will be called (to see, how to overload a copy assignment operator, see this)
Now, let's have a look at your code snippet:
A *p=new A();
A *q=new A();
*p=*q;
In the first statement A *p=new A();, default constructor will be called to create an object (in this case, new object will be created on heap) and p will be initialized with the address of the newly created object (as p is a pointer)
Similar is the case with second statement A *q=new A(); (It is creating another object and q will be initialized with newly created object)
Now, the third statement: *p = *q; (here * is Dereference operator)
To understand, what the third statement is doing, let's have a look at some pointers and de-referencing them to get the actual object, which they're pointing to.
int someVariable = 5;
int *somePointer = &someVariable;
// ...
*somePointer = 7;
Let's try to understand the above code snippet: someVariable is created and initialized with a value of 5, then somePointer is created and initialized with the address of someVariable.
Now, the last statement *somePointer = 7;, it is actually de-referencing the somePointer and by de-referencing, it'll get the the variable which it is pointing to. (so it will get someVariable) and then it is assigning 7 to it. So after this statement, someVariable's value will become 7
Let's have another example:
int* somePointer = new int;
int* anotherPointer = new int;
// ...
*somePointer = 5;
*anotherPointer = 7;
// ...
*somePointer = *anotherPointer;
First, somePointer will be created and initialized with the address of dynamically allocated int variable (will be allocated in heap, see Dynamic Allocation in c++), similarly, anotherPointer will be initialized with the address of another dynamically allocated variable.
Then, it is assigning 5 to the first variable (which is being pointed by somePointer) and 7 to the second variable (which is being pointed by anotherPointer)
Now, the last statement will be of your interest, *somePointer = *anotherPointer;, in this statement *somePointer is de-referencing and getting the first variable (whose value was 5) and *anotherPointer is de-referencing and getting the second variable (whose value is 7), and it is assigning the second variable to the first variable, resulting in changing the first variable's value to 7.
Now, let's have a look at your *p=*q; statement, (p was pointing to the first object of A, and q was pointing to the second object of A, both dynamically allocated), *p will dereference p and get the first object, *q will dereference q and get the second object, and then the second object will be copied in the first object, and if you see, no new object is being created in *p=*q;, and only the value of second object is being created in the first object, so copy assignment operator will be called here and no the copy constructor.
Another thing
You should de-allocate the dynamically allocated memory which you borrowed using new operator:
delete p;
delete q;
You should add these two lines at the end of your program, so to avoid Memory Leak.
As stated in the comments, one need to understand the basics first:
With A *p=new A(); one gets a pointer to a memory region on the heap in which an object of type A is constructed.
With *p one dereferences the pointer, i.e. one retrieves the object.
Now *p = *q uses the (possibly implicitly declared) assignment operator of class A in order to give *p -- the object pointed to by p -- the value of *q. This operation could equivalently be written as p->operator=(*q).
The last step, the assignment, is identical to what you would obtain with objects instead of pointers (which is usually a better way to go in C++ and often called RAII):
A r;
A s;
r=s;
I have seen several examples of copy assignment operator and could not understand why do we need to delete pointers inside copy assignment operator. For example if I have the following class
class MyClass
{
public:
MyClass(int a)
{
x = new int(a);
}
MyClass& operator=(const MyClass& pMyClass)
{
*x = *(pMyClass.x);
// ?????????
// delete x;
// x = new int(*(pMyClass.x));
}
~MyClass()
{
delete x;
}
private:
int* x;
}
What is wrong with *x = *(pMyClass.x) line? I am just copying object pointed by pMyClass.x why I need to delete and create it again?. Could anyone please give example when this code will cause memory leak?
So this is an example [extracted from Bjarne Stroustrup's "A tour of C++ (2nd edition)] of a copy assignment of a user defined vector class:
Vector& Vector::operator=(const Vector& a) // copy assignment
{
double∗ p = new double[a.sz];
for (int i=0; i!=a.sz; ++i)
p[i] = a.elem[i];
delete[] elem; // delete old elements
elem = p; // here elem is the vector's data holding member array
sz = a.sz;
return ∗this;
}
To understand why at line 6 we have the deletion operation:
delete[] elem; // delete old elements
we first need to first understand the distinction between copy constructor and copy assignment. In the first case (copy constructor) we create a completely new object, whereas in the second case (copy assignment, the one we're actually interested in) we already have an existing object into which we just want to copy the contents of another given object of the same type.
Given the fact that we already have an existing object, we first need to clear it's contents so that we are then able to copy the desired content from the object we intent to copy.
I hope that answers your question.
It is a valid code. But if instead of the pointer to a single object you will have a pointer to first element of an array and arrays may have different sizes then you need to delete the array that to reallocate it with the new size.
Nothing wrong with *x = *(pMyClass.x) when you copying value from one class instance to other. I think, in general, deleting an object (if it is not just int) can prevent usage of new object with new data if before operator= execution address stored in x was sent to some other part of program.
I am a student so I apologize up front for not using the correct forum protocols. I have searched for hours on this problem, none of my classmates can help. My assignment is to create a copy constructor, overloaded assignment operator(=) and a destructor (the 'big three') in C++ to manage an array on the heap. What I wrote below in VS13 produces the correct output but I get a debug error: HEAP CORRUPTION DETECTED:c++ crt detected that the application wrote to memory after end of heap buffer
Can anyone give me some guidance on this, I don't even know where to look. Thanks!!
//copy constructor
myList::myList(const myList& source){
cout << "Invoking copy constructor." << endl;
array_capacity = source.array_capacity; //shallow copy
elements = source.elements; //shallow copy
delete[] arrayPointer;
arrayPointer = new double(source.array_capacity); //deep copy
for (int i = 0; i < array_capacity; i++) //copy array contents
{
arrayPointer[i] = source.arrayPointer[i];
}
}
//overloaded assignment operator
myList& myList::operator=(const myList& source){
cout << "Invoking overloaded assignment." << endl;
if (this != &source){
array_capacity = source.array_capacity; //shallow copy
elements = source.elements; //shallow copy
delete[] arrayPointer; //delete original array from heap
arrayPointer = new double(array_capacity); //deep copy
for (int i = 0; i < source.array_capacity; i++) {//copy array contents
arrayPointer[i] = source.arrayPointer[i];
}
}
return *this;
}
//destructor
myList::~myList(){
cout << "Destructor invoked."<< endl;
delete[] arrayPointer; // When done, free memory pointed to by myPointer.
arrayPointer = NULL; // Clear myPointer to prevent using invalid memory reference.
}
There are a couple of problems with your code. First you are invoking delete on arrayPointer but it hasn't been initialized to anything. This could in fact end up deleting memory you have already allocated or result in an excecption or asset in the implementation of delete. Second when you do initialize it you are allocating a single double initialized to the value of source.array_capacity. Notice the parenthesis used in the line below.
arrayPointer = new double(source.array_capacity);
This will certainly result in undefined behavior during the copy as you end up accessing elements outside the bounds of the array. The above line is present in both your copy constructor and copy-assignment operator and should be using square brackets instead like so:
arrayPointer = new double[source.array_capacity];
You also never check to see if there are any elements stored in the source instance of myList. In this case you should likely be assigning nullptr (or NULL in C++03) to arrayPointer.
As a side note you do not really need to assign NULL to arrayPointer in your destructor. Once the object is destroyed it's gone and any attempt to access it after the fact will result in undefined behavior anyway.
Captain Obvlious pointed out the problem in your copy-constructor already.
You will have noticed that the copy-constructor and the assignment-operator contain a lot of the same code but with a subtle difference. In fact this is probably how you ended up with the error (the assignment operator needs to delete[] the old value, but the copy-constructor doesn't.
Code duplication is bad because it leads to subtle errors like this creeping in. A good pattern you can use here is what's called the copy and swap idiom.
The gist is that you define the copy-constructor, and you also define swap. Then you get assignment for free. This works because swap is easier to implement correctly than the assignment operator, and another major benefit is that nothing can go wrong (you don't have to worry about out-of-memory errors and so on).
In your code; keeping your fixed copy-constructor, you could add inside the class definition:
friend void swap( myList &a, myList &b )
{
std::swap( a.array_capacity, b.array_capacity );
std::swap( a.arrayPointer, b.arrayPointer );
std::swap( a.elements, b.elements );
}
and now the assignment operator is very simple:
myList& myList::operator=(const myList &source)
{
myList temp(source);
swap(*this, temp);
return *this;
}
The old resources from the current object are deleted by the destructor of temp. This version doesn't even need to check for self-assignment because std::swap(x, x) is well-defined.
This can even be optimized further by taking source by value instead of by reference, as explained on the linked page.
Consider for example a template container class that holds a buffer that is allocated on the heap:
T *_buffer = new T[SIZE]
Just a simple pointer to c array of type T.
This class is templated. However I am having issues with performing a deep copy of an object into my buffer.
In my unit test, i set up a test class:
class test
{
public:
int* _ptrInt;
test() {_ptrInt = nullptr;}
test(const int i)
{
_ptrInt = new int;
*_ptrInt = i;
}
test(const test& other)
{
_ptrInt = new int;
*_ptrInt = *other._ptrInt;
}
~test()
{
delete _ptrInt;
}
};
on my container I call set, passing a temporary as the data:
container.set(0, test(5));
// destructor called on copy immediately after statement, invalidating deep copy in buffer
void set (const int& index, const T& data)
{
int i = realign(index);
T copy = data;
_buffer[i==SIZE?i-1:i] = copy; // ternary statement and index work
}
however, _buffer takes copy as a reference, the moment copy goes out of scope, it deletes the same pointer that is held in the _buffer. I am trying to force the _buffer to assign by value. But I have had no luck.
memcpy still copies the pointers to point to the same address
test copy constructor is correctly called
move semantics would require class to have move constructor
std::vector somehow implements this to copy correctly, whether its T/T*, heap/stack, with/without move constructor, so I know it must be possible
Is there a way I can assign by value to the _buffer on the heap?
You are "assigning by value." However, your test class doesn't implement the assignment operator operator=, so the assignment invokes the compiler-generated default assignment operator which simply copies member-by-member. Hence the problems with shallow assignment.
Also, your copy constructor will explode if other._ptrInt is nullptr.
A copy constructor is used for many things such as when I need to use pointers or dynamically allocate memory for an object. But looking at this example at tutorialpoint.com:
#include <iostream>
using namespace std;
class Line
{
public:
int getLength( void );
Line( int len ); // simple constructor
Line( const Line &obj); // copy constructor
~Line(); // destructor
private:
int *ptr;
};
// Member functions definitions including constructor
Line::Line(int len)
{
cout << "Normal constructor allocating ptr" << endl;
// allocate memory for the pointer;
ptr = new int;
*ptr = len;
}
Line::Line(const Line &obj)
{
cout << "Copy constructor allocating ptr." << endl;
ptr = new int;
*ptr = *obj.ptr; // copy the value
}
Line::~Line(void)
{
cout << "Freeing memory!" << endl;
delete ptr;
}
int Line::getLength( void )
{
return *ptr;
}
void display(Line obj)
{
cout << "Length of line : " << obj.getLength() <<endl;
}
// Main function for the program
int main( )
{
Line line(10);
display(line);
return 0;
}
the result is :
Normal constructor allocating ptr
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Freeing memory!
and when I commented out (the copy constructor) and the code inside destructor I got the same results:
Normal constructor allocating ptr
Length of line : 10
So what is the difference between using the copy constructor here or not? Also why does "Freeing Memory!" occur twice?
The argument to the display() function is passed by value, so the compiler calls the copy constructor to create it. When the class defines its copy constructor you get the correct semantics: the copy constructor makes a copy, and that copy has its own memory to hold the length. When you remove the copy constructor, the compiler generates one for you, and the copy that gets passed to display() has the same pointer as the original. When that copy gets destroyed it deletes the memory that ptr points to. When the original gets destroyed it deletes the same memory again (which happens to have no visible effects here). That's definitely not what you want to have happen, which is why you need to define a copy constructor. As #Joe says: inside the destructor, print the value of `ptr' to see this more clearly.
Print the address of the memory being freed.
I believe you will find the compiler generated the constructor for you, did a value copy of the contents, including the pointer, and you are double-freeing the pointer and just getting lucky that the runtime isn't complaining about it.
The compiler generated copy constructor is still being called - nothing has changed in that regard, you just aren't printing anything from it since you didn't write it.
If we don’t define our own copy constructor, the C++ compiler creates a default copy constructor for each class which does a member wise copy between objects. The compiler created copy constructor works fine in general. We need to define our own copy constructor only if an object has pointers or any run time allocation of resource like file handle, a network connection..
A constructor of some type T of the form
T (const & T);
The single argument must be a const reference to an existing object of same type
Creates a duplicate of the existing object
Used whenever a copy of an object is needed
Including arguments to functions, results returned from functions
Problems with pointer-based arrays in C++:–
No range checking.
Cannot be compared meaningfully with ==
No array assignment (array names are const pointers).
If array passed to a function, size must be passed as a separate argument.