Click here to Skip to main content
15,867,308 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I can't be the first to notice this, or maybe it IS just me, but I was trying to use the in place syntax for the new operator for a data structure class I was writing, and when I ran it in _DEBUG mode, the compile exited with some verbiage about unrecognized syntax.

I assume that the macro that overloads new in _DEBUG mode doesn't include a version to handle the in-place syntax, but a review of both Code Project and the web at large didn't reveal any information on the subjet. Any ideas as to what the story is? I worked around this by wrapping the offending code between two #ifdef _DEBUG blocks like so ...

CObject* pPtr;

#ifdef _DEBUG
#pragma push_macro("new")
#undef new
#endif

new (pPtr) CObject;

#ifdef _DEBUT
pragma pop_macro("new")
#endif


... but I would like to know if this is a failing of the preprocessir, or something I'm missing.
Posted

It is not really failing in the preprocessor, it is a fairly well known limitation of the debug implementation. The preprocessor does textual substitution, so that the preprocessor does something like:

#ifdef _DEBUG
#define new _debugnew(__FILE__, __LINE__)
#endif


The preprocessor will then happily replace all instances of new with _debugnew(__FILE__, __LINE__) in your code. The implementation needs to provide an implementation of _debugnew, for instance:

C#
void * operator new (size_t size, char const * file, int line)
{
  logallocation(size, filem line);
  return ::new char [size];
}


This works fairly well for the majority of uses of C++ memory allocation, i.e. for use of global new but does not work for all of them, as you have found.

As well as the way you got round this, you could possibly provide your own implementation of the debug new operator, that would get called in debug mode, e.g.

class MyClass
{
public:
  void* operator new(size_t size)
  {
    return newImplementation(size);
  }

  void* operator _debugnew(size_t size, char const * file, int line)
  {
    return newImplementation(size);
  }

private:
  void* newImplementation(size_t size)
  {
    // your fancy implementation here
  }
};


Note, that what is replaces new depends on your compiler - you will need to dig into the system files to find out what is actually used in debug mode.
 
Share this answer
 
Comments
Michael Waters 19-Apr-11 17:06pm    
But the issue of the inplace syntax is key (literally). I have a string hash table with a previously allocated bucket, practically a copy of CMapStringToOb (that's how I found my soltion, because it's what Micorsoft does), and it uses the inplace syntax to instantiate an empty string key for each new bucket in the hash. I'll try your approach and see what happens.
Michael Waters 3-May-11 12:47pm    
It's been a couple of weeks since I had a chance to implement this approach, and I ran into another obstacle. It seems that CString (which I'm using as the key to my hash table implementation) doen't overload the inplace new operator at all. So even after I derive a class from CString and overload it's inplace new operator, the compiler still spits out that it doesn't recognize the class-specific inplace new operator. I couldn't figure out WHY that was the case, until I ran across the following http://www.gotw.ca/publications/mill15.htm
, which explained why it is if CString doesn't overload the inplace new, my own overload won't compile.

So, it looks like I will have to rewrite my hash table to use a different key (probably a copy of CString, with the appropriately overloaded new operator), but I doubt I'll get a chance to do that level of rewrite any time in the near future. I thiknk I will go ahead and accept this solution, tentatively, since I'm pretty sure, from my research, that this approach will prove correct.

That's an awful lot of work just to make _DEBUG report line numbers! And here I thought I was asking a question that was going to have a simple solution :)
personally, i wouldn't undefine the debug version of new if i were you, its a very helpful tool, why not just change your syntax up a bit so that its ok with it? like graham said, macros aren't perfect but they do get the job done.
 
Share this answer
 
Comments
Michael Waters 19-Apr-11 17:14pm    
I only undefine the debug version for the one particular code block - and I might mention that when I tracked down the MFC code and saw what it was doing, it explained all those CMap memory leaks reported in the Output window that didn't have line numbers attached to them. I would think after all these years, the MFC code would have been modified with a better work around than just "don't do that".
The mysterious new operator. The operator new isnt a macro. You can overload the global new operator with your own memory management function. Therefore you should ALWAYS delete a class created by new in the same context.
Example to overload new:
#define	USE_NEW	3
#if(0==USE_NEW)
	// default behaviour
#elif(1==USE_NEW)
void* operator new( size_t cb )
{
  void* res = HeapAlloc(GetProcessHeap(),0,cb);
  return res;
}
void operator delete( void* p)
{
  if(p) HeapFree(GetProcessHeap(),0,p);
}
#elif(2==USE_NEW)
#include <objbase.h>
#pragma comment (lib,"ole32.lib")
void* operator new( size_t cb )
{
  void* res = CoTaskMemAlloc(cb);
  return res;
}
void operator delete( void* p)
{
  if(p) CoTaskMemFree(p);
}
#elif(3==USE_NEW)
void* operator new( size_t cb )
{
  void* res = GlobalAlloc(GMEM_FIXED,cb);
  return res;
}
void operator delete( void* p)
{
  if(p) GlobalFree((HGLOBAL)p);
}
#endif</objbase.h>

Regards.
 
Share this answer
 
Comments
Albert Holguin 18-Apr-11 21:00pm    
he's talking about the _DEBUG macro that replaces new, doesn't say that new is a macro
mbue 19-Apr-11 0:02am    
And i told him there is no macro (to push), its a simple overload - one for release and another for debug. and everybody can declare his own private overload for new.
Regards.
Michael Waters 19-Apr-11 17:10pm    
Interesting approach, but I don't think it's quite the solution I need.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900