I'm looking at the following code:
// operator new example
#include <iostream> // std::cout
#include <new> // ::operator new
struct MyClass {
int data[100];
int kk;
MyClass(int ea) : kk(ea) {std::cout << "constructed [" << this << "]\n";}
};
int main () {
std::cout << "1: ";
MyClass * p1 = new MyClass(1);
// allocates memory by calling: operator new (sizeof(MyClass))
// and then constructs an object at the newly allocated space
std::cout << "2: ";
MyClass * p2 = new (std::nothrow) MyClass(2);
// allocates memory by calling: operator new (sizeof(MyClass),std::nothrow)
// and then constructs an object at the newly allocated space
std::cout << "3: ";
new (p2) MyClass(3);
// does not allocate memory -- calls: operator new (sizeof(MyClass),p2)
// but constructs an object at p2
// Notice though that calling this function directly does not construct an object:
std::cout << "4: ";
MyClass * p3 = (MyClass*) ::operator new (sizeof(MyClass));
// allocates memory by calling: operator new (sizeof(MyClass))
// but does not call MyClass's constructor
delete p1;
delete p2;
delete p3;
return 0;
}
And I have two questions:
Is the object 2 destroyed when executing the line
new (p2) MyClass(3);
that should construct the object 3 in the object 2's allocated space?
The line
MyClass * p3 = (MyClass*) ::operator new (sizeof(MyClass));
also works without the ::, what's the purpose of the scope resolution operator used without a class/namespace before it?
Firstly, no, the second object's destructor is not called. A new object is just initialized in its place. If you like, you can explicitly call the destructor of the object with p2->~MyClass(); before you reuse its memory.
Secondly, the purpose of using :: to qualify the allocation function is to make sure it comes from the global namespace. The standard implicitly defines two overloads of operator new for all translation units, and if you include <new>, you get a few extras. All of these are defined in the global namespace (not in std). It's possible to overload operator new for classes (simply provide them as member functions), so qualifying with :: makes sure the global version is used instead.
Answer1: The object located at p2's lifetime ends when you reuse it's memory for a new object. It won't have its destructor run so it's not "destroyed" cleanly, although with only POD members and no user-declared destructor, in this case it makes no difference.
Answer2: Using :: forces the lookup for operator new to only consider operator new declared at global scope. In the scope which you are calling operator new, there is no other operator new that would be considered in any case, so it makes no difference.
Related
I have written the following code for placement new and delete operator functions. Can you please tell the issue with the code below.
// new_operator.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
using namespace std;
class Mem
{
public:
void* alloc(size_t sz) { return malloc(sz); }
void dealloc(void* ptr) { free(ptr); }
};
class Object
{
public:
Object() { cout << "In Constructor Object()" << this << endl; }
~Object() { cout << "In Destuctor ~Object()" << endl; }
void* operator new(size_t sz, Mem* handle)
{
Object* x1 = (Object*)handle->alloc(sz);
return x1;
}
void operator delete(void* ptr, Mem* handle)
{
cout << "Here\n";
((Object*)(ptr))->~Object();
handle->dealloc(ptr);
}
};
int main()
{
Mem* memory = new Mem;
Object* obj = new (memory) Object;
cout << "Obj is " << obj << endl;
delete (obj, memory);
delete memory;
return 0;
}
I'm getting runtime crashes at the time when delete operator function starts executing. Can anyone please tell what I'm doing wrong.
Placement delete is called to free memory when a constructor called from placement new fails. You are not supposed to call any destructors from any version of operator delete, because operator delete frees memory that is left after an object that used to reside there is destroyed (or was never constructed to begin with).
The only way to explicitly call a placement operator delete is to spell out two words operator delete, thus making a function-call-expression. You cannot invoke it from a delete-expression (there is no placement-delete-expression syntax). In your case, you would need to use a qualified name: Object::operator delete. Note that if you remove the explicit destructor call from Object::operator delete, as you should because of the above, the destructor will not be called. There is no way to both invoke the destructor and free the memory in a single call to a placement delete. The easiest way to handle this is to create and use a non-static member function, say void Object::destroy(Mem*).
delete (obj, memory);
On this line, you delete only memory, not obj. The left hand operand of comma operator is discarded. Since the expression obj has no side-effects, this is probably a mistake.
delete memory;
On this line, you delete memory again. This results in undefined behaviour.
Note that you never destroy the dynamic Object that you created. The custom placement delete overload will only be called in case the placement new throws an exception. In other cases, your malloc will leak.
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/
I have a few doubts related to destructor.
class cls
{
char *ch;
public:
cls(const char* _ch)
{
cout<<"\nconstructor called";
ch = new char[strlen(_ch)];
strcpy(ch,_ch);
}
~cls()
{
//will this destructor automatically delete char array ch on heap?
//delete[] ch; including this is throwing heap corruption error
}
void operator delete(void* ptr)
{
cout<<"\noperator delete called";
free(ptr);
}
};
int main()
{
cls* cs = new cls("hello!");
delete(cs);
getchar();
}
Also, as a destructor is automatically called upon delete why do we need an explicit delete when all the logic can be written in destructor?
I am super confused regarding operator delete and destructor and couldn't make out their specific usage. An elaborate description would be very helpful.
EDIT:
My understanding based on the answers:
For this particular case, a default destructor will corrupt the char pointer so we need to explicitly delete the char array first other wise it will result in memory leak. Please correct me if I am wrong.
Well, a default destructor deallocates memory that is used by member variables (i.e. the member pointer ch itself ceases to exist), but it does not automatically deallocate any memory that is referenced by member pointers. So there is a memory leak in your example.
delete is not a function (though you can overload it); and yes, it is good practice that the logic for the deallocation be written in the destructor. But it is incorrect to assume that the deallocation will be automatically performed by the destructor. The thing is that the destructor will be called at the end of the object's lifetime, but what it does it dependent upon the code you write for it. That is, you should call delete[] on ch inside the destructor:
~cls()
{
delete[] ch;
ch = nullptr;
}
Moreover, I believe the heap corruption error is coming from that fact that you did not leave enough room in the initialization of ch for the null byte \0. You should also be using the the member-initializer list. Change your constructor to this:
cls(const char* _ch) : ch(new char[1+strlen(_ch)])
{
std::cout << "\nconstructor called";
std::strcpy(ch, _ch);
}
There are many improvements that can be made to your code. Namely, using std::string and following the Rule Of Three. Your code also doesn't need a operator delete() overload. cs should be stack allocated:
#include <iostream>
#include <string>
class cls
{
std::string ch;
public:
cls() { std::cout << "default constructor called\n"; }
cls(std::string _ch) : ch(_ch)
{
std::cout << "constructor called\n";
}
cls(cls const& other) : ch(other.ch)
{
std::cout << "copy-constructor called\n";
}
~cls() { std::cout << "destructor called\n"; }
};
int main()
{
cls cs("hello!");
std::cin.get();
} // <-- destructor gets called automatically for cs
No, the destructor won't magically delete the memory pointed to by ch for you. If you called new (you did in the constructor) then you must also call delete at some appropriate time.
A destructor executes when an object is being destroyed. This can be when an automatic object (that is something allocated on the stack) is about to go out of scope, or when you explicitly delete an object allocated with new.
Generally, think of new as a way of getting memory allocated, a constructor as a way of taking that memory and making it into an object, a destructor as taking an object and destroying it, leaving behind a chunk of memory and delete as taking that chunk of memory and deallocating it.
As a convenience for you, when you call new the compiler will call the constructor for you after it allocates the memory you requested and when you call delete the compiler will automatically invoke the destructor for you.
You are getting heap corruption errors because you have a buffer oveflow: you are not allocating space for the null terminating byte that strcpy appends.
Remember a C string is a sequence of bytes followed by a null byte. This means that a string of length 5 actually requires 6 bytes to store.
Also remember that you can and should use std::string instead of C style arrays to save yourself the trouble and avoid having to write error-prone code when there's a very robust and full-featured implementation already available for your use.
With the notable exception of homework/learning exercises, there is hardly a situation where you should implement C style strings directly instead of using std::string.
The same (albeit a little less strict) goes for dynamic arrays in general. Use std::vector instead.
There is no use in override the delete Operator for a specific class. That's what the global delete Operator is for.
What you should do is a delete[] on ch in the destructor. This has to be done explicitly, as the delete Operator only deallocates the memory directly allocated to store the class' instance. As you are allocating further Memory in the constructor you have to free it upon destruction.
As a rule of thumb you can assume that con- and destructor need to be coded symmetricly. For every new in the constructor, has to be a delete in de destructor.
Oh and by the way: You must not mix C++ allocators (new/delete) with C allocators (malloc/free). What you allocate in C++, you have to free in C++ and vice versa.
C++ memory magnament is based on RAII. That means that destructors are called when the lifetime of a variable ends.
For example:
class Foo
{
public:
Foo() { cout << "Constructor!!!" << endl; }
~ Foo() { cout << "Destructor!!!" << endl; }
};
int main()
{
Foo my_foo_instance;
}
Prints:
Constructor!!!
Destructor!!!
Because the constructor is called in the initiallization of my_foo_instance (At the declaration), and the destructor is called when the lifetime of my_foo_instanceends (That is, at the end of main() ).
Also, this rules works for any context, including class attributes:
class Foo1
{
public:
Foo1() { cout << "Foo1 constructor!!!" << endl; }
~ Foo1() { cout << "Foo1 destructor!!!" << endl; }
};
class Foo2
{
private:
Foo1 foo1_attribute;
public:
Foo2() { cout << "Foo2 constructor!!!" << endl; }
~ Foo2() { cout << "Foo2 destructor!!!" << endl; }
};
int main()
{
Foo2 my_foo2_instance;
}
Prints:
Foo1 constructor!!!
Foo2 constructor!!!
Foo2 destructor!!!
Foo1 destructor!!!
The trace of the program is:
Main starts
Initiallization of my_foo2_instance: Call to Foo2 constructor
First of all, Foo2 initializes its attributes: Call to Foo1 constructor
Foo1 has no attributes, so Foo1 executes its constructor body: cout << "Foo1 constructor" << endl;
After attributes initiallization, Foo2 executes its constructor body: cout << "Foo2 constructor" << endl;
End of main scope, so end of my_foo2_instance lifetime: Call to Foo2 destructor
Foo2 destructor executes its body: cout << "Foo2 destructor" << endl;
After the destructor, the lifetime of the attributes of Foo2 ends. So: Call to Foo1 destructor
Foo1 destructor executes its body: cout << "Foo1 destructor" << endl;
After the destructor, the lifetime of the attributes of Foo1 ends. But Foo1 has no attributes.
But what you forget is that a pointer its a basic type, so it has no destructor. To destroy the object pointed by the pointer (Thats is, finallize the life of the pointee object), use use delete operator in destructor body.
Destructor never deallocates anything on its own accord. Destructor will only implicitly call destructors for class subobjects and execute whatever code you put into the destructor's body. Since in your case the subobject ch is of raw pointer type, it has no destructor. So nothing will be done in your case. Since it is you who allocated the memory, it is you who's responsible for deallocating it. In short, yes, you do need that delete[] ch in your destructor.
If you want that memory deallocated automatically, use a smart pointer class instead of a raw pointer. In that case the destructor of your class will automatically call the destructor of the smart pointer subobject, which will deallocate memory for you. In your specific example an even better idea would be to use std::string to store the string inside the class object.
The heap corription in your case is caused by the fact that you allocate insufficient memory for your string, which leads to an out-of-bounds write in strcpy. It should be
ch = new char[strlen(_ch) + 1];
strcpy(ch,_ch);
The extra space is needed for the terminating zero character.
My take:
1) The short answer is no.
2) As for "why not", consider the following example:
cls create()
{
cls Foo("hello"); // This allocates storage for "ch"
return Foo;
} // Return variable is by value, so Foo is shollow-copied (pointer "ch" is copied).
// Foo goes out of scope at end of function, so it is destroyed.
// Do you want member variable "ch" of Foo to be deallocated? Certainly not!
// Because this would affect your returned instance as well!
Recommendations:
If you want to see whether your code leaks storage, you may use an excellent tool valgrind, http://valgrind.org/
As for what to read to understand this topic better, I would recommend the standard C++ literature, plus have a look at smart pointers, e.g. unique pointer
http://www.cplusplus.com/reference/memory/unique_ptr/
which will help you understand the topic and everything will be put to place.
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.
It is my understanding that when you make a copy of a class that defines a pointer variable, the pointer is copied, but the data that the pointer is pointing to is not.
My question is: Is one to assume that the "pointer copy" in this case is simply instantiating a new pointer (dynamic memory allocation) of the same type? Eg., the new pointer is simply a new allocation containing an arbitrary memory address and one should take care to point that new pointer to the appropriate memory address?
I presume there is a quite simple answer to this question, and I apologize for its trivial nature, but I am trying to understand pointers at a deeper level and this came up upon my researching pointers on the internet.
Regards,
Chad
The pointer will be simply copied as a value - so both classes will point to the same original memory, no new allocation takes place. Shallow copy - this is what the language does by default.
If you need to allocate new memory and make a copy of the data you have to do that yourself in the copy constructor. Deep copy - you have to do this yourself
edit: This is one of the advantages of C++, you are free to decide how copying works. It might be that a copy of the object which only does read access to the memory can avoid the cost of copying the memory. You can also implement classes which only make a copy of the original data if the new object needs to do a write.
First off, the pointer in your class is static, (i.e. the compiler knows that there is a pointer in this class and what size it is, so no dynamic memory allocation is needed when the class is instantiated).
If you copy the class (and have not special copy constructor defined) then the pointer in the new class will point to the same place in memory as the pointer in the old class. To clarify:
#include <iostream>
class A {
public:
int *p;
};
int main() {
A a,b;
a.p = new int(10);
b = a;
std::cout << "*(a.p) = " << *(a.p) << std::endl; // 10
std::cout << "*(b.p) = " << *(b.p) << std::endl; // 10
*(b.p) = 3;
std::cout << "*(a.p) = " << *(a.p) << std::endl; // 3
std::cout << "*(b.p) = " << *(b.p) << std::endl; // 3
return 0;
}
Now if you want to allocate new memory when copying, you need to write a copy constructor and a copy assignment constructor:
#include <iostream>
class A {
public:
int *p;
A() : p(0) {}
A(const A& other) { // copy constructor
p = new int(*other.p);
}
A& operator=(const A& other) { // copy assignment constructor
// protect against self assignment
if (this != &other) {
if (p != 0) {
*p = *other.p;
} else { // p is null - no memory allocated yet
p = new int(*other.p);
}
}
return *this;
}
~A() { // destructor
delete p;
}
};
int main() {
A a,b;
a.p = new int(10);
b = a;
std::cout << "*(a.p) = " << *(a.p) << std::endl; // 10
std::cout << "*(b.p) = " << *(b.p) << std::endl; // 10
*(b.p) = 3;
std::cout << "*(a.p) = " << *(a.p) << std::endl; // 10
std::cout << "*(b.p) = " << *(b.p) << std::endl; // 3
return 0;
}
When you do this you should also write a destructor (see Rule of three ), because the memory that is being allocated in the copy / copy assignment constructors needs to be de-allocated if the class is destroyed:
Pointers don't instantiate dynamic memory allocation. Pointers and allocations are entirely different things.
If you copy a pointer that points to dynamically allocated memory, you have two pointers pointing at the same allocated memory. Since you've copied it, it already points to the memory block. Specifically, if using the compiler-generated copy constructor, the new pointer will point to the exact same thing as the old pointer. You don't need to do anything with it if that's OK.
You do have the problem of when to free the memory. Freeing it twice will typically cause heap corruption, which is nasty. Not freeing it will cause a memory leak, which may be acceptable in some circumstances. Freeing it before the other pointer is through with it will also cause problems. For this reason, people who have multiple pointers to the same memory often go to the Boost project and use their shared_ptr template (which will be in the upcoming new Standard, and is present in most up-to-date systems).
If you want each pointer to point to separate chunks of memory, you have to set that up by writing your own copy constructor, and allocating a new chunk and copying necessary data in it. (You also need to write your own assignment operator, for the exact same reasons, and your own destructor so you can free the memory. There's a rule of thumb, called the Rule of Three, that says if you need to write your own copy constructor, assignment operator, or destructor, you probably need to write all of them.)
The copied pointer will point to the exact same address. There's no new allocation.
Yes, pointers simply contain memory addresses, if you want to make a deeper copy you need to code that yourself, in the copy constructor.
If you're always referencing the same kind of data via a pointer from the same class, and need to copy the data along with the objects, you could also consider making it just a plain member, not a pointer.