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.
Related
In a situation where I want to avoid dynamic memory allocations, I'm replacing the new operator with a process that essentially uses the memory of some statically allocated object (the Storage class below). You can see a minimum working example below:
#include <cassert>
#include <iostream>
struct Object {
Object() { std::cout << "Creating a new object\n"; }
static void *operator new(size_t);
static void operator delete(void *p);
};
static struct {
Object where;
bool allocated = false;
} Storage; // 1
void *Object::operator new(size_t) {
assert(!Storage.allocated);
auto p = ::new (&Storage.where) Object; // 2
Storage.allocated = true;
return p;
}
void Object::operator delete(void *p) {
assert(Storage.allocated);
static_cast<Object *>(p)->~Object();
Storage.allocated = false;
}
int main() { Object *obj = new Object; } // 3
My question has to do with the number of calls to the constructor. When I run the above program, I expect to call the constructor twice (marked as 1 and 2 in the comments above) but the output I get is:
Creating a new object
Creating a new object
Creating a new object
Why is the constructor called thrice? I'd only expect constructor calls, by the static object and the call to placement new. I tried tracing the code with gdb, but it makes no sense to me, since position //3 is where the third call to the constructor originates.
The reason I want to know is because a case has emerged, where this extra constructor call causes unwanted side-effects; up until now, this extra call was unnoticed.
For some odd reason, your operator new calls the constructor when it should just allocate memory. This means that the call to new winds up calling the constructor of Object twice. There is one call in operator new and another call in main.
You probably want this:
void *Object::operator new(size_t) {
assert(!Storage.allocated);
Storage.allocated = true;
return reinterpret_cast<void *> (&Storage.where);
}
Imagine if the constructor took an integer parameter and the line in main looked like this:
Object *obj = new Object(7);
How would operator new know how to properly construct the object? That's not where you're supposed to do that!
Object *obj = new Object; does two things:
Allocates memory by calling operator new
Calls the constructor.
Your operator new calls the constructor as well, so the constructor is called twice by this statement (and once for the global variable initialization).
Note that delete is the same. delete obj; does two things:
Calls the destructor.
Deallocates memory by calling operator delete
Your operator delete shouldn't call the destructor either, because then the destructor is called twice.
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.
Here's what I'm doing:
#include <iostream>
using namespace std;
class Test
{
public:
int i;
Test();
Test(int x);
~Test();
static void operator delete(void * t);
};
Test::Test() : i(1) { cout << "constructing" << endl; }
Test::Test(int x) : i(x) { cout << "constructing w/ arg" << endl; }
Test::~Test() { cout << "destructing" << endl; }
Test::operator delete(void *self)
{
cout << "deleting" << endl;
((Test *) t)->~Test(); // call destructor since it isnt called otherwise
::delete(t); // actually delete memory
}
template <typename T> // too lazy to figure out correct type
void callback(Test *t, T fn)
{
(fn)(t); // delete operator is implicitly static so this syntax is correct
}
int main()
{
Test *t = new Test();
callback(t, &Test::operator delete); // deletes t
}
I've noticed that unless operator delete is overloaded for my class, the previous snippet will fail to compile. If it's included, it will compile and work as expected (first the constructor is called, then overloaded delete, then the destructor, each exactly once).
I thought of passing the global delete operator ::operator delete, but that doesn't work either (I get an unresolved overloaded function call). I can call it without trying to get its address just fine.
Is what I'm doing even possible without defining my own overload of ::operator delete?
I know that there is basically no use case where I'd ever need to use something like this. I know that ::operator delete is not a general use thing, and that it doesn't call destructors....
Global operator new/delete are overloaded functions - you'll need to cast to the correct function pointer type:
callback(t, static_cast<void(*)(void*)>(::operator delete));
Edit: I'm expanding my answer to clarifiy some things.
It is true that the destructors are not called by the global operator delete. It's just deallocation function responsible to return the memory back to runtime. Calling destructors is the job of delete expression:
Delete expression first calls the destructors of the object (or objects, if we use array form) its pointer argument points to and then calls the deallocation function (if the pointer being deleted is of class type, it looks for it in the scope of that class first and calls the global one if it doesn't find it).
Another important thing to note is that using a void* pointer in delete expression is undefined behaviour, which is what you do in your overload:
cout << "deleting" << endl;
((Test *) self)->~Test();
::delete(self); // this is delete expression using void*, UB
You're not calling global operator delete, for that you'd need to say ::operator delete(t);. You have a delete expression and the scope resolution operator just tells it to not look inside class scope for deallocation function.
If you change it to this ::delete( (Test*) self); you'll see destructing being printed twice, again UB.
All in all, don't call the destructor inside operator delete, it's not its job.
I have the following code
#include <iostream>
#include <cstddef>
#include <string>
#include <memory>
class Object
{
public:
Object()
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
std::string x;
void *operator new( size_t bytes )
{
std::cout << __PRETTY_FUNCTION__ << " : bytes = " << bytes << std::endl;
}
void operator delete( void * arg )
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
int main( int c, char *v[] )
{
// std::auto_ptr< Object > pObject( new Object() );
Object *o = new Object();
delete o;
}
and it produces this output...
static void* Object::operator new(size_t) : bytes = 8
and then core dumps.
Given that I don't get the output from the operator delete() method and that it core dumps. I'm assuming that my operator delete() method isn't being invoked.
Can anyone shed any light as to why it isn't being invoked?
Thank you for focusing on the core dump against my ALL CAPS RANTS because it actually turned out to be the problem.
EDIT--
Ok, Where do I start.... I'm incredibly sorry for ranting. We've all been there, under pressure to meet a deadline and something innocuous appears to be causing an issue and we're convinced it's one thing when in fact it's another.
This has taught me a valuable lession... I need to start listening....
I fully appreciate all of help and advice given here.
Thx
Mark.
Your new expression does two things. It invokes the appropriate operator new function to allocate some memory and then constructs a new Object in the memory pointed to by the return value of operator new.
As you don't have a return statement in your operator new you get undefined behaviour. If we explore what is likely to happen, it is likely that the function returns a random value for the return value and the compiler attempts to construct the Object (including its owned std::string) at an invalid address.
This will cause a crash before your code ever reaches the delete statement.
operator new must return a pointer to sufficient memory (or throw an exception), because the new-expression will also be trying to invoke the constructor of Object for the allocated memory. The problem is not with delete, it's new Object that cannot complete normally.
If I change main to be
int main( int c, char *v[] )
{
// std::auto_ptr< Object > pObject( new Object() );
Object *o = new Object();
std::cout<<"I'm ok here"<<std::endl;
delete o;
}
then I get
static void* Object::operator new(size_t) : bytes = 4
Bus error
and cout is never called.. This is because you are running into undefined behaviour. (In particular it looks like on many compilers the constructor is being called in the location that is undefined)
If I change new to be
void *operator new( size_t bytes )
{
std::cout << __PRETTY_FUNCTION__ << " : bytes = " << bytes << std::endl;
return new char[bytes];
}
I get
static void* Object::operator new(size_t) : bytes = 4
Object::Object()
I'm ok here
static void Object::operator delete(void*)
so delete will be called if you do the right thing.
You're crashing well before delete() is called, because you haven't allocated any storage for std::string x; - if you comment out this instance variable then the code should compile (with warnings) and run OK.
Why doesn't your operator new return a value? It is declared to return void * but dosn't return anything. This means your compiler should have given a compile error, apparently it didn't, and well the crash may be becaue of that.
On the other hand, if this, as you say, is an example, then maybe you returned 0 from new, in which case operator delete is not being invoked because calling delete on a 0 pointer is equivaent to an empty statement.
malloc something in new and return it, and operator delete will be invoked
Let's be more specific here:
Your core dump is obviously because you don't return a value.
delete o is a delete expression which will only eventually call your operator delete, and it will do so ONLY if the pointer is not NULL. As said, it must be a valid pointer
I would have thought that the fact your constructor wasn't being called either was a bit of a clue. As is the fact that you've got a segmentation fault going on when you run it. What happens with new Object()? Your memory is allocated (this is your operator new) and then your constructor is called. How is your constructor called? By dereferencing the pointer to your allocated memory....
If you stub out your operator new, everything works fine: you get the memory from the runtime, the constructor is called, the operator delete is called. If you make an operator new that actually does things, you'll see operator delete (and your constructor) getting called too.
I'd like to use boost.pool. It's okay if you don't know about it. Basically, it has two main functions, malloc() and free().
I've overloaded new and delete for my custom defined class test.
class test
{
public:
test()
{
cout << "ctor" << endl;
}
~test()
{
cout << "dtor" << endl;
}
void* operator new(size_t) throw()
{
cout << "custom operator new" << endl;
return _pool.malloc();
}
void operator delete(void* p)
{
cout << "custom operator delete" << endl;
_pool.free(p);
}
void show()
{
cout << _i << endl;
}
private:
int _i;
static boost::pool<> _pool;
};// class test
boost::pool<> test::_pool(sizeof(test));
When I create instance of test using new, constructor was not called but if I delete it, destructor was called. Why? and can I avoid it?
Can't reproduce, when added
#include <iostream>
#include <boost/pool/pool.hpp>
using namespace std;
(why do people omit such things that are necessary to make the code compile?!) and
int main()
{
test* p = new test;
delete p;
}
This is either a stripped-down and modified version that doesn't have that behavior or your compiler may be broken (which version is it?)
In any case your aim should be getting the constructor called, rather than getting destructor not called. Overloaded operator new just deals with raw memory allocation, the built-in new-expression should use that to obtain the memory and then call the constructor to create an instance there.
Edit: the only way I can reproduce your output is by circumventing the built-in new-expression:
test* p = static_cast<test*>(test::operator new(sizeof (test)));
Could it be because the global operator new is getting called? Anyways, just a comment about your class...
operator new and operator delete are always static (even if you don't write the keyword), so it's good practice to use static in the declaration.
You declared operator new with throw(), meaning that it won't throw. But you use a statement (iostreaming) that can throws. Maybe you should surround that with try/catch and create an std::nothrow_t version.