PDA

View Full Version : TinyXML and Overriding new Operators


SpreeTree
10-17-2005, 02:11 PM
In my current engine, I override the new and delete operators using the following code



#ifdef _DEBUG
#define MARY_DEBUG_NEW new(__FILE__, __LINE__)
#else
#define MARY_DEBUG_NEW new
#endif

#define new MARY_DEBUG_NEW



I then override the new operator with the following function calls


inline void *operator new(size_t size, const char *_file, int _line)
inline void *operator new[](size_t size, const char *_file, int _line)
inline void *operator new(size_t size)
inline void *operator new[](size_t size)


Each one of these calls HeapNew, which deals with the actual allocation of memory.

This seems to cause problems when I start to use XML.

When I include "tinyxml.h", it falls over on the line


rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap));


with the error


error C2661: 'operator new' : no overloaded function takes 2 arguments


If I include the xml files with my MFC code (using the above new overrides), it falls over in the same place with the following errors


error C2665: 'operator new' : none of the 5 overloads can convert parameter 1 from type 'const char [74]'
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\new.h(100): could be 'void *operator new(size_t,const std::nothrow_t &) throw()'
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\new.h(108): or 'void *operator new(size_t,void *)'


Now I appreciate what the error is telling me, but I am unsure as to how to override the new operator again to deal with this one.

Any one encountered this before?

Thanks
Spree

Reedbeta
10-17-2005, 05:39 PM
don't redefine new until after you've included the XML headerfile?

this would prevent you from tracing memory allocations in the XML module (assuming that's what you're doing), but then you shouldn't really need to anyway...

corey
10-17-2005, 05:53 PM
At a glance, it looks like the call with operator new in TinyXML is not allowing the translation to operator new (size_t, ...) .

Re-defining the actual keyword new is a bad idea. What happens when you define a class overload?

However, if you want to use it like MFC does, you must define it after includes and before implementations to avoid behavior described above.

corey

SpreeTree
10-17-2005, 11:52 PM
don't redefine new until after you've included the XML headerfile?

this would prevent you from tracing memory allocations in the XML module (assuming that's what you're doing), but then you shouldn't really need to anyway...

My memory management does more than just allow for the tracking of memory leaks, so I do want to track the use of new in tinyXML, and every other library that I use.


Re-defining the actual keyword new is a bad idea.


Could you please expalin why? I appreciate it does cause me some problems (this one being a case in point) but as I mentioned above, I need (or want would be a better word) to track all memory allocation, so I need to override new to track allocation in external libraries.

Spree

corey
10-18-2005, 08:00 AM
It is bad when used in the manner you're showing.

If you re-defining it specifically before implementation that only uses new calls and not operator new calls, then it should be ok.

Do not re-define it before a class or in a header that might overload an operator new because then you're doing text replacement in the definition!

I say it's bad in general. It's ok within a specific context.

corey

dave_
10-18-2005, 09:04 AM
Could you please expalin why?


If you do that you cant subsequently overload operator new and delete as it replaces the keyword with arbitary things like MARY_DEBUG_NEW or new(__FILE__, __LINE__)

SpreeTree
10-18-2005, 01:35 PM
If you do that you cant subsequently overload operator new and delete as it replaces the keyword with arbitary things like MARY_DEBUG_NEW or new(__FILE__, __LINE__)

Ok , I see that, and it would be an issue if I intended to overwrite new in any other way, so I guess I am safe for now!

But, for future reference (and maybe for implementation now), what other way would produce the same effects?

Spree

corey
10-18-2005, 05:37 PM
Well, instead of redefining the actual "new" call, you could just define a different macro and use that in place of new and operator new.

You don't *have* to use the new keyword.

corey

SpreeTree
10-18-2005, 11:58 PM
You don't *have* to use the new keyword.


In my case, I do. The memory manager is there to not only cover the memory allocation in my native code, but to track memory allocation throught the application, including the various libraries I use.

If I didn't redefine the new keyword, then I would not be getting the required information from my external libraries (granted I still don't get all of it, but most is better then none), and people using my code would have to use a different keyword for the same ends, which I don't want to force on them.

Spree

ThomasYoung
10-19-2005, 01:12 AM
[edit]Hmm.. ignore the following, I just noticed that you need file and line. ;-D[edit]

You should be able to achieve what you want without messing around with macros at all.
If you define non-inline replacements for the global operators somewhere in your project then the linker should use these in preference to the built-in versions.
These definitions can then be wrapped by #ifdef DEBUG.

e.g. (in a .cpp somewhere in your project):

#ifdef DEBUG
#include <stdlib.h>

void PlatformDebugBreak();

static unsigned long totalAllocated = 0;
static unsigned long maximumAllocated = 0;

void*
operator new(size_t size)
{
size_t sizeToMalloc = size + sizeof(size_t);
size_t* result = reinterpret_cast<size_t*>(malloc(sizeToMalloc));
if(sizeToMalloc && !result)
{
PlatformDebugBreak();
}
totalAllocated += size;
if(totalAllocated > maximumAllocated)
{
maximumAllocated = totalAllocated;
}
*result = size;
return result + 1;
}
void
operator delete(void* ptr)
{
if(!ptr)
{
return;
}
size_t* ptrToSizeT = reinterpret_cast<size_t*>(ptr);
--ptrToSizeT;
totalAllocated -= *ptrToSizeT;
free(ptrToSizeT);
}
void*
operator new[](size_t size)
{
size_t sizeToMalloc = size + sizeof(size_t);
size_t* result = reinterpret_cast<size_t*>(malloc(sizeToMalloc));
if(sizeToMalloc && !result)
{
PlatformDebugBreak();
}
totalAllocated += size;
if(totalAllocated > maximumAllocated)
{
maximumAllocated = totalAllocated;
}
*result = size;
return result + 1;
}
void
operator delete[](void* ptr)
{
if(!ptr)
{
return;
}
size_t* ptrToSizeT = reinterpret_cast<size_t*>(ptr);
--ptrToSizeT;
totalAllocated -= *ptrToSizeT;
free(ptrToSizeT);
}
#endif

SpreeTree
10-19-2005, 02:14 AM
]Hmm.. ignore the following, I just noticed that you need file and line. ;-D

Unfortunatly yes. Its normally not important but does help with the tracking of memory leaks (allowing you to double click in the output stream of Dev Studio and go straight to the file and line), and is something i cant live without.

Spree

grinliz
10-19-2005, 10:47 AM
I pushed a new version of TinyXML (2.4.2) that should fix the overloaded new and delete problem.

lee

corey
10-19-2005, 12:39 PM
In my case, I do. The memory manager is there to not only cover the memory allocation in my native code, but to track memory allocation throught the application, including the various libraries I use.

In that case, you'll just have to make it work by ensuring the re-definition is past any awkward headers.

It looks like the TinyXML author has shown up? I've been meaning to ask him about parsing well-formed strict XHTML with it.

corey

SpreeTree
10-19-2005, 01:41 PM
I pushed a new version of TinyXML (2.4.2) that should fix the overloaded new and delete problem.

lee

Excellent.

Thanks for the swift fix Lee, I'll try and download the new version tonight and let you know how it does :)

Spree

grinliz
10-19-2005, 01:57 PM
corey -

Well formed strict XMTML is probably a better topic for the TinyXML forums on Sourceforge. (Especially since I haven't tried it, but others there have.)

grinliz

corey
10-19-2005, 02:19 PM
No worries, it was just a comment.

corey

SpreeTree
10-19-2005, 02:37 PM
Version 2.4.2 works a treat, thanks for that! :)

Spree