Overloading new and delete in C++.

G

Guest

Hi all,
I've been using C++ for quite a while now and I've come to the point where I need to overload new
and delete inorder to track memory and probably some profiling stuff too. I know that discussions of
new and delete is a pretty damn involved process but I'll try to stick to the main information I'm looking for
currently. I've searched around for about the last too weeks and have read up on new and overloading it to
some extent but there are still a few mysteries to me. First of all, how is the constructor called in relation
to a 'new' operator?
Foo* NewFoo = new Foo();
In most tutorials on overloading 'new', they usually put malloc in the body of the 'new' and, of course,
they put free() in the corresponding delete. But I thought that the reason you use new/delete was that
malloc doesn't call the constructor and free won't call the destructor.. but I don't see where or how
the constructors/destructors get called when you overload 'new' if you use malloc inside the overloaded
'new' and free in the overloaded 'delete'.

I have a Tracer class that I am trying to use to trace allocations and deallocations in my classes,
so currenlty all I really want to do is to have a new operator that is overloaded so that is passes in
both the filename and linenumber and then just use 'new' normally. Currently I'm not trying to using
any other allocater (though I'd like this solution to be flexible enough that I could) so all I really am
trying to do is something like this :
void * operator new (unsigned int size, char const * file, int line)
{
void * p = new (size);
if (Tracer::Ready)
NewTrace.Add (p, file, line, size);
return p;
}
I know this code won't work (I couldn't get it to compile) but consider it the pseudo code for what I'm
trying to accomplish.

I've also seen a few articles about using a class new operator. I only have a few base classes and I
only want to track the memory in my classes really, would it be possible to over load the new operator
for my base classes and have them work in my derived classes? Is there an accepted or
preferred way of overloading new and delete so that only extra functionality is added but the
actual new and delete are still used, like in the above pseudocode where the call to overloaded new actually
does call new it just does a few extra things?

Also on a different topic, is there a defined way that objects are destructed when they go out of scope?
In this case my Tracer in instantiated right above my main(), but I also have a static vector of objects
in a factory class. It looks like my non-static Tracer goes out of scope and is therefore destroyed
before the static vector is destructed. That does make some sense but I wanted to know for sure if this
is what is being done or does it only destruct in that order because of the way the compiler works,i.e. its
undefined in the standard?
Any bizzareness of this post is a direct lack of sleep :)
Any help would be much appreciated.
 
J

John Harrison

Hi all,
I've been using C++ for quite a while now and I've come to the point where I need to overload new
and delete inorder to track memory and probably some profiling stuff too. I know that discussions of
new and delete is a pretty damn involved process but I'll try to stick to
the main information I'm looking for
currently. I've searched around for about the last too weeks and have read
up on new and overloading it to
some extent but there are still a few mysteries to me. First of all, how
is the constructor called in relation
to a 'new' operator?
Foo* NewFoo = new Foo();
In most tutorials on overloading 'new', they usually put malloc in the
body of the 'new' and, of course,
they put free() in the corresponding delete. But I thought that the reason you use new/delete was that
malloc doesn't call the constructor and free won't call the destructor.. but I don't see where or how
the constructors/destructors get called when you overload 'new' if you use malloc inside the overloaded
'new' and free in the overloaded 'delete'.

You are confusing the new operator with operator new (easy to do). Operator
new just allocates memory, so using malloc is fine. On the other hand the
new operator calls operator new and then calls whatever constructor is
required.

Ditto for the delete operator and operator delete.
I have a Tracer class that I am trying to use to trace allocations and deallocations in my classes,
so currenlty all I really want to do is to have a new operator that is
overloaded so that is passes in
both the filename and linenumber and then just use 'new' normally.
Currently I'm not trying to using
any other allocater (though I'd like this solution to be flexible enough
that I could) so all I really am
trying to do is something like this :
void * operator new (unsigned int size, char const * file, int line)
{
void * p = new (size);
if (Tracer::Ready)
NewTrace.Add (p, file, line, size);
return p;
}
I know this code won't work (I couldn't get it to compile) but consider it the pseudo code for what I'm
trying to accomplish.

Now you are talking about placement new, do you know the syntax to invoke
placement new?

I'd guess this should be fine, but untested code.

void * operator new (size_t size, char const * file, int line)
{
void * p = operator new(size);
if (Tracer::Ready)
NewTrace.Add (p, file, line, size);
return p;
}

Again you seem to have confused operator new with the new operator. Your
overloaded operator new should call the normal operator new, not the new
operator. Personally I would just call malloc however.

I've also seen a few articles about using a class new operator. I only have a few base classes and I
only want to track the memory in my classes really, would it be possible to over load the new operator
for my base classes and have them work in my derived classes?

Yes that works.
Is there an accepted or
preferred way of overloading new and delete so that only extra functionality is added but the
actual new and delete are still used, like in the above pseudocode where
the call to overloaded new actually
does call new it just does a few extra things?

Its the preferred way.
Also on a different topic, is there a defined way that objects are
destructed when they go out of scope?
In this case my Tracer in instantiated right above my main(), but I also
have a static vector of objects
in a factory class. It looks like my non-static Tracer goes out of scope and is therefore destroyed
before the static vector is destructed. That does make some sense but I
wanted to know for sure if this
is what is being done or does it only destruct in that order because of
the way the compiler works,i.e. its
undefined in the standard?

The order of construction of static objects in different files is undefined
(in the same file they are constructed in order of declaration). The order
of destruction is always the reverse of the order of construction.
Any bizzareness of this post is a direct lack of sleep :)
Any help would be much appreciated.

john
 
P

Patrik Stellmann

Here's an example that might help (should compile as is):

#include <iostream>
using namespace std;

class Base
{
public:
Base();
void* operator new(size_t size, char const * file, int line);
void operator delete(void* p);
};

class Derived :
public Base
{
public:
Derived();
};


Base::Base()
{
cout << "Base::Base()" << endl;
}

void* Base::eek:perator new(size_t size, char const * file, int line)
{
void* p = malloc(size);
// <tracing>
cout << "New called! file: " << file << ", line: " << line << ", size:
" << size << ", p: " << p << endl;
// </tracing>
return p;
}

void Base::eek:perator delete(void* p)
{
// <tracing>
cout << "Delete called! p: " << p << endl;
// </tracing>
free(p);
}


Derived::Derived()
{
cout << "Derived::Derived()" << endl;
}

int main()
{
Base* x = new(__FILE__, __LINE__) Derived;
delete x;
return 0;
}
 
Y

Yakov Lerner

... I need to overload new
and delete inorder to track memory and probably some profiling stuff too. I know that discussions of
new and delete is a pretty damn involved process but I'll try to stick to the main information I'm looking for
currently.... First of all, how is the constructor called in relation
to a 'new' operator?
Foo* NewFoo = new Foo();
^^^^^^^^^
You probably thought that all 'new Foo()' did is call the overloaded new.
No, it does two things:
(1) calls olverloaded new (or default new if no overlodaded new was defined)
(2) calls constructor on pointer returned by (1)
As a result of this login, you don't need to invoke constructor
inside your overloaded new, and it would be bad mistake to invoke it.
This is why it's fine to call malloc() from overloaded new.

Similarly, 'delete p' does two things:
(a) calls destructor p->~Foo()
(b) called default or overloaded delele()

You don't see any explicit lines of code for (1) or (a). Compiler
silently arranges for this.

You can see steps 1,2,a,b if you put prints into ctor, dtor, and into
overloaded new, and into overloaded delete. I suggest that yu do this
and see what happens.

JL
 
S

Simon Turner

Hi all,
I've been using C++ for quite a while now and I've come to the point where
I need to overload new and delete inorder to track memory and probably
some profiling stuff too. I know that discussions of new and delete is a
pretty damn involved process but I'll try to stick to the main information
I'm looking for currently. I've searched around for about the last too
weeks and have read up on new and overloading it to some extent but there
are still a few mysteries to me.

You probably want to read the standard sections 3.7.3 [basic.stc.dynamic],
5.3.4 [expr.new] and 5.3.5 [expr.delete] if you have access to a copy.

Also, have a look at Stroustrup's TC++PL if you have it.
First of all,
how is the constructor called in relation to a 'new' operator?

Foo* NewFoo = new Foo();

The 'new Foo()' above is a new expression, not a straight call to operator
new(). It will call Foo::eek:perator new() if it exists and ::eek:perator new()
otherwise to allocate the memory for your new Foo instance, and then invoke
the constructor to initialise the returned raw memory.

It should look something like the following pseudocode:

// allocate raw mem:
void* mem = ::eek:perator new(sizeof Foo);
//
// or: void* mem = Foo::eek:perator new(sizeof Foo);

// construct Foo instance in mem using placement new,
// does any housekeeping and calls constructor
new(mem) Foo;

return static_cast said:
In most tutorials on overloading 'new', they usually put malloc in the
body of the 'new' and, of course, they put free() in the corresponding
delete. But I thought that the reason you use new/delete was that malloc
doesn't call the constructor and free won't call the destructor.. but I
don't see where or how the constructors/destructors get called when you
overload 'new' if you use malloc inside the overloaded 'new' and free in
the overloaded 'delete'.

As above the new expression calls operator new() to allocate memory and then
initialises it using the constructor. The delete expression calls the
destructor to destroy the object and then operator delete() to release the
memory.

The idea is that operator new returns raw memory which the constructor turns
into an object, and the destructor is used to turn that object back into raw
memory before operator delete deallocates it.
I have a Tracer class that I am trying to use to trace allocations and
deallocations in my classes, so currenlty all I really want to do is to
have a new operator that is overloaded so that is passes in both the
filename and linenumber and then just use 'new' normally. Currently I'm
not trying to using any other allocater (though I'd like this solution to
be flexible enough that I could) so all I really am trying to do is
something like this :

void * operator new (unsigned int size, char const * file, int line)
^^^^^^^^^^^^^^^^^
size_t size
{
void * p = new (size);
try:
void * p = ::eek:perator new(size);
if (Tracer::Ready)
NewTrace.Add (p, file, line, size);
return p;
}

I'm not certain that'll work and haven't tried it, but it seems like that
should work fine with

Foo* f = new(__FILE__,__LINE__) Foo;
I know this code won't work (I couldn't get it to compile) but consider it
the pseudo code for what I'm trying to accomplish.

I've also seen a few articles about using a class new operator. I only
have a few base classes and I only want to track the memory in my classes
really, would it be possible to over load the new operator for my base
classes and have them work in my derived classes?
Yes.

Is there an
accepted or preferred way of overloading new and delete so that only extra
functionality is added but the actual new and delete are still used, like
in the above pseudocode where the call to overloaded new actually does
call new it just does a few extra things?

class Foo {
public:
// this applies to instances of Foo and any subclasses.
void* operator new(size_t size)
{
// do stuff
return ::eek:perator new(size);
}
};
Also on a different topic, is there a defined way that objects are
destructed when they go out of scope? In this case my Tracer in
instantiated right above my main(), but I also have a static vector of
objects in a factory class. It looks like my non-static Tracer goes out of
scope and is therefore destroyed before the static vector is destructed.
That does make some sense but I wanted to know for sure if this is what is
being done or does it only destruct in that order because of the way the
compiler works,i.e. its undefined in the standard?

I don't think the order in which statics and globals are destroyed is
defined.

The order in which local variables are destroyed when they go out of scope
is defined, but I can't even think of a sensible ordering for statics and
globals.
 
U

Uwe Schnitker

Hi all,
I've been using C++ for quite a while now and I've come to the point where I need to overload new
and delete inorder to track memory and probably some profiling stuff too. I know that discussions of
new and delete is a pretty damn involved process but I'll try to stick to the main information I'm looking for
currently. I've searched around for about the last too weeks and have read up on new and overloading it to
some extent but there are still a few mysteries to me. First of all, how is the constructor called in relation
to a 'new' operator?
Foo* NewFoo = new Foo();

Well, the new expression shown is translated by the compiler into something
like (Pseudocode):

Foo* NewFoo = new Foo(); => void* tmp = allocation_function(sizeof(NewFoo);
NewFoo::constructor(tmp);

(This is simplistic, the compiler has to take care of possible exceptions,
etc.)

First an allocation function is called to aquire memory, then the constructor
is called.

What makes the thing confusing, is that the allocation function is called
"operator new". So the "new expression" results in a call to the "operator
new function", plus a constructor call.
In most tutorials on overloading 'new', they usually put malloc in the body of the 'new' and, of course,
they put free() in the corresponding delete. But I thought that the reason you use new/delete was that
malloc doesn't call the constructor and free won't call the destructor.. but I don't see where or how
the constructors/destructors get called when you overload 'new' if you use malloc inside the overloaded
'new' and free in the overloaded 'delete'.

The answer is, you don't overload "operator new" or the "new expression",
because you cannot. You can overload a function called "operator new".

The result is that - in Pseudocode - in

Foo* NewFoo = new Foo(); => void* tmp = operator new(sizeof(NewFoo);
NewFoo::constructor(tmp);

the overloaded "operator new function" is called, followed by a constructor
call.

This is different to, say, the plus operator:

c = a + b; => c = a.operator+(b);
or
c = a + b; => c = operator+(a,b);

where the whole + expression is taken care of by the overloaded operator.
I have a Tracer class that I am trying to use to trace allocations and deallocations in my classes,
so currenlty all I really want to do is to have a new operator that is overloaded so that is passes in
both the filename and linenumber and then just use 'new' normally. Currently I'm not trying to using
any other allocater (though I'd like this solution to be flexible enough that I could) so all I really am
trying to do is something like this :
void * operator new (unsigned int size, char const * file, int line)
{
void * p = new (size);
if (Tracer::Ready)
NewTrace.Add (p, file, line, size);
return p;
}
I know this code won't work (I couldn't get it to compile) but consider it the pseudo code for what I'm
trying to accomplish.

I've also seen a few articles about using a class new operator. I only have a few base classes and I
only want to track the memory in my classes really, would it be possible to over load the new operator
for my base classes and have them work in my derived classes?

Well, if you change the pseudocode to:

Foo* NewFoo = new Foo(); => void* tmp = NewFoo::eek:perator new(sizeof(NewFoo);
NewFoo::constructor(tmp);

you can imagine that a class specific overload is indeed possible.
Is there an accepted or
preferred way of overloading new and delete so that only extra functionality is added but the
actual new and delete are still used, like in the above pseudocode where the call to overloaded new actually
does call new it just does a few extra things?

Try adding a member function

void * operator new (unsigned int size, char const * file, int line)
{
void * p = ::eek:perator new (size);
if (Tracer::Ready)
NewTrace.Add (p, file, line, size);
return p;
}
to your class NewFoo.

Create instances with:

NewFoo* ap = new("s",1) NewFoo;

This should give you a first idea of the concepts behind not
overloading "operator new", but overloading the function
"operator new".

There is a lot more to discover, e.g. writing the corresponding
"operator delete" function overload.

<SNIP>

Good luck,

Uwe
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,071
Latest member
MetabolicSolutionsKeto

Latest Threads

Top