473,405 Members | 2,354 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

Overloading new and delete in C++.

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.

Jul 22 '05 #1
5 5199

<Ey*****@squirm.net> wrote in message
news:10*************@news.supernews.com...
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
Jul 22 '05 #2
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::operator 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::operator 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;
}

Jul 22 '05 #3
<Ey*****@squirm.net> wrote:
... 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
Jul 22 '05 #4
<Ey*****@squirm.net> wrote in message news:<10*************@news.supernews.com>...
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::operator new() if it exists and ::operator 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 = ::operator new(sizeof Foo);
//
// or: void* mem = Foo::operator new(sizeof Foo);

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

return static_cast<Foo*>(mem);

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 = ::operator 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 ::operator 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.

Any bizzareness of this post is a direct lack of sleep :)
Any help would be much appreciated.

Jul 22 '05 #5
<Ey*****@squirm.net> wrote in message news:<10*************@news.supernews.com>...
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::operator 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 = ::operator 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
Jul 22 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: HeroOfSpielburg | last post by:
I'm writing a memory manager and overloading the operators "::new" and "::delete" I know this isn't always the smartest thing to do, but regardless, I was wondering what sort of considerations I...
3
by: Nimmi Srivastav | last post by:
There's a rather nondescript book called "Using Borland C++" by Lee and Mark Atkinson (Que Corporation) which presents an excellent discussion of overloaded new and delete operators. I am...
0
by: Tim Milstead | last post by:
(CODE AT END OF POST) I have got some code for finding memory leaks that works well with: new() and needs to be extended to work with new
3
by: silver360 | last post by:
Hello, I'm trying to create a basic Heap manager and i have some question about new/delete overloading. The following code give me this output : >> $./heap >> registered : 0x804d098 >>...
3
by: md | last post by:
Hi, the following code is working for static objects. ie the statement IntArray x(20); my problem is i want to use this overloading operator for dynamically created objects...
3
by: toton | last post by:
Operator overloading has a sort syntax rather than member function call for stack based memory allocation. like complex<int> c1,c2,c3; c3= c1+c2; How the same can be applied to heap based...
9
by: learning | last post by:
hi I am trying to make some simple app to learn exception safety coding. I know that new and delete can throw bad_alloc but how can I force them to throw by a flag "change" at run time? I am...
3
by: Lighter | last post by:
The C++ Standard Doesn't Permit Overloading new and delete? In the 13.5 of The C++ standard (ISO/IEC 14882, 1998), I cannot find the specification on overloading the operators new and delete;...
5
by: Jerry Fleming | last post by:
As I am newbie to C++, I am confused by the overloading issues. Everyone says that the four operators can only be overloaded with class member functions instead of global (friend) functions: (), ,...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.