class implementation of operator delete() not being invoked
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 delet开发者_StackOverflow中文版e( 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.
精彩评论