Sign in to follow this  

MemMgr: calling global delete from (global) overloaded delete

This topic is 4846 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

It sounds that I'm trying to do weird thing, isn't it? ;) Hovewer, problem is real, read on... I'm trying to code dynamic memory manager, it should work this way: calling new adds new entry to list of memory allocations (file name, line, address etc.), calling delete erases appropiate entry from list. At the end of program, if there are left any entries in the list, it means that code couses memory leaks! and all un-erased entries are logged to a file. Now, I've read some very good articles about how such memory system should work (Gems #2 and article on Flipcode) but there's one little problem - they've built their system on malloc and free, what doesn't fit my needs - especially constructors and destructors (they *must* be called). Question 1: is there any way to automatically call constructor for object created on heap by malloc, having only that pointer and nothing else? I've looked in Visual new implementation, it actually calls malloc, but after it, it calls some very strange looking functions, macros etc. I've tried to make my own new implementation ;) by copying those, but it didn't even compile (missing #includes, eventually I had to include hundreds of them...). Maybe there's easier way than that... Question 2: in my code I have overloaded delete in this way: void operator delete( void * _address) { if (!_address) return; getMemMgr.DeallocateMemory( _address, SC :: at_Delete ); } where DeallocateMemory should erase memory entry and eventually delete the pointer, but... it can't! couse when it calls: delete _address; // or ::operator delete (_address);, same efect then my overloaded version gets called, once again calling DeallocateMemory, then delete and so on, cousing infinite recursion. And it's real problem for me, couse it's the last thing that I need to overcome to have my memory mgr work nicely and gracefully. And that's a question for all of you, C++ coding gurus: is there any special way (or cheap trick or macro trickery or ...) that would allow me to do such thing? I would be *really* gratefull if anyone could help me :) (and one last thing, second question is much more important than first)

Share this post


Link to post
Share on other sites
Constructors and destructors ARE called when you implement new and delete with malloc and free.
operator new does this:
Execute body of operator new
Construct object in place with the returned pointer

operator delete does this:
Destruct object
Execute body of operator delete.

Remember to overload the array versions too.

Share this post


Link to post
Share on other sites
1) yes and no, for malloc it won't be possible unless you implement malloc in terms of new :), but if you overload global new (which might call malloc in your implementation) it will call the constructor automatically.

2) your DeallocateMemory() should never call delete itself, it's a mistake in your code if it does that.

Share this post


Link to post
Share on other sites
Hello Koshmaar,

You can't call the compiler new or delete if you actual defined new global new and delete. :(

Now that being said here some things to look at.

I believe the "new" in standard C++ should only allocates space, it is the compiler that adds a call to constructor of a class if a new for a class/struct use involved.

Next delete only frees space. Compile adds a call to the destructor before actual delete is called.

So if you want to overload global new and delete then find out what new and delete do and do same in your version of new and delete and add any other code you need or what.

Now one way you could still use global new/delete is to have each class overload new/delete. This would allow you to still use global new and delete by way of ::new ::delete.

There are a many examples on the web for doing this.

Lord Bart :)

Share this post


Link to post
Share on other sites
Hi guys, thx for your replies :-)

Paradigm Shifter:
Quote:
Constructors and destructors ARE called when you implement new and delete with malloc and free.
Execute body of operator new
Construct object in place with the returned pointer


Hmmm, I didn't new that... anyway, for me, that's a godsend. As I understand, new calls constructor for the returned pointer, ok, but what if malloc couldn't allocate any memory on heap so we have to return 0? Logically, constructor shouldn't been called, but what if it do sth else ie. it throws an exception? I don't want any exceptions in my code ;-) but nevermind, there are more improtant questions to ask.

Baraclese:
Quote:
2) your DeallocateMemory() should never call delete itself, it's a mistake in your code if it does that


Yes, it called it couse I was getting more and more frustrated with aformentioned behaviour, and I was trying more and more strange looking solutions :-)

Quote:

Now one way you could still use global new/delete is to have each class overload new/delete. This would allow you to still use global new and delete by way of ::new ::delete.


No no no, it would be nasty, ugly and repetive work. Now, when I (theoretically) finally know the answer to my problems, I can do the normal globall delete overload, which calls free() and have... stupid erros?!
Yes, stupid errors :-/ I've written very simple program, here it is:



#include "SC.h" // engine's main file, included for logging stuff

class Foo
{
public:
Foo() { log("- Foo constructor") }
~Foo(){ log("- Foo destructor") }
};

void * operator new( size_t _size, const char * _file, SC :: usint _line )
{
log(_file)
return malloc(_size);
}

void operator delete( void * _address)
{
if (!_address) return;
log("Delete...")

free(_address);
}


int main(int argc, char* argv[])
{

SC :: InitLogFile();

log("Before new...")
Foo* fooPtr = new ("bleble",1) Foo;
log("After new")

log("Before delete...")
delete fooPtr;
log("After delete")

SC :: ShutdownLogFile();
return 0;
};




And the logfile looks very strange:

1 : Before new...
1 : Delete...
1 : Delete...
1 : Delete...
1 : Delete...
//... etc. hundreds of such lines, looks like infinite recursion

What's more strange, is the fact that when debugging line-after-line, it breaks on log("Before new...") and I'm absolutely sure that logging is ok.
Hovewer, now I also know where the possible bug may hide: it's the overloaded delete. It's global, so compiler might use it for destroying other things... ie. strings that I create in log(), but it would be very weird couse logging is included in compiled library! is it possible for compiler to change method of creating objects for such library? :-/ Or I am making other stupid error?

EDIT: fixed source tag

Share this post


Link to post
Share on other sites
You should redefine the normal new, not just the one with file and line. Why? Because anything that uses the normal new is going to call your overloaded delete, since there is only one delete ever called (except when constructor (or is it new?) throws an exception).

Also, what does you log do? If it needs memory, it's going to allocate it, which will need to log it, which needs memory, infinitly.

To Do:
overload new(size)
overload delete(size,file,line) in case constructor (or new?) throws exception
overload new[](size)
overload delete[](size)
overload new[](size, file, line)
overload delete[](size, file, line) in case of exceptions in construction (or new?)

often used other funcs
overload new(size, memptr) returns memptr - placement new. Useful to cause constructor to run, and vtable to be setup in memory you've allocated via some other method (like realloc for dynamic arrays).

Share this post


Link to post
Share on other sites
Thx Namethatnobodyelsetook, you saved my butt :-) As you've suggested (and what was strange at first glance), I've overloaded every possible operator that news/deletes memory and now my test program works! constructors and destructors are properly called. Hovewer, when I add log() to delete( void * _address) then it starts all over again:

Quote:

If it needs memory, it's going to allocate it, which will need to log it, which needs memory, infinitly.


Nevermind, thx for the help :-) my memory mgr isn't already working, so there may be another questions to (all of) you...

Share this post


Link to post
Share on other sites
Hey, it's me (again)! I've got another (stupid) theoretical question :-) Remember when the Namethatnobodyelsetook said:

Quote:

You should redefine the normal new, not just the one with file and line. Why? Because anything that uses the normal new is going to call your overloaded delete, since there is only one delete ever called (except when constructor (or is it new?) throws an exception).


I've read it again and now it doesn't look so simple and straightforward...

First, in my memory mgr I want to track only the memory which has been allocated using the extended new(_size, _file, _line ) so for me default behaviour of new(_size) is absolutely sufficient. Normal new(.) will be used by things like STD and STL implementations, while new(...) will be wrapped by define:

#define new new(__FILE__,__LINE__)

and I will use headers "new_on" and "new_off" to define or undefine new so that, for example, the <vector> will use normal new:

#include "new_off.h"
#include <vector>
#include "new_on.h"
#include "memMgr.h"
#inlcude "othersThatUseMemMgr.h"

or simply use this:

#define New new(__FILE__,__LINE__)

so that additional headers won't be needed.

Hovewer, there is one problem more.
I have overloaded global delete, which will be called for STD/STL/etc. things and my code; but when called for STD/STL it will search in map for nonexisting memory node! and that would be bad, very bad. In ideal situation I would want to have one normal delete that would be called for STDthings (allocated using normal new(.)) and one delete that would be called only when deleting objects allocated by extended new(...).
In summary, I want to track memory usage of my, and only my code; I trust third party libraries in that they won't leak memory :-)
Is there any solution to meet my requirments? Or am I so stupid that I see problems where they don't exist? :-)

Share this post


Link to post
Share on other sites
Overload new and delete in your class, or tracked everything, those are your only real choices.

You could make your new new, allocate like normal, then allocate a seperate info node. When you delete, you search for the info node, and free it, if it exists. This will make memory delete operations unbearably slow.

Just stick your tracking structure on everything. You can include a flag to say, "it's not mine!" when using standard new if you want.

Share this post


Link to post
Share on other sites
Quote:
Just stick your tracking structure on everything. You can include a flag to say, "it's not mine!" when using standard new if you want.


There are times, when heterosexual male have a wish to kiss other man.

...

No no no! don't look at me so strange! sometimes it's normal thing.

[/me smashes (*this) in head]

Of course ! it's so simple and fill my needs in 100%!!! How could I be so stupid?!?!? :->

Share this post


Link to post
Share on other sites

This topic is 4846 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this