Using Debug Heap from C++

OK. I discovered this Debug Heap thing. it is awesome, but I am having problems using it with the new operator. When I use malloc and when there's a memory leak, the line number and filename of the allocation statement is correctly displayed. However, if I use new, the line number and filename ALWAYS point to crtdbg.h(552) which is where the new operator calls the debug version of new:
inline void* __cdecl operator new(unsigned int s)
        { return ::operator new(s, _NORMAL_BLOCK, __FILE__, __LINE__); }

Since the call is being made in the crtdbg.h file, the wrong line number and file is being recorded! Now, one might say that above, the operator new is declared inline, so the call should be replaced by the debug version of new. That doesn't seem to happen. I thought that probably expansion of inline functions is disabled in the DEBUG mode, so I turned it on from the project settings, but still, I get the wrong line number and file!
Please help, otherwise this GREAT feature will be useless to me!
mamyunAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

nietodCommented:
Here is a preprepared answer that should cover what you need--and a bit more.  Let me know if you have any questions.

**********************************

You need to call the _CrtSetDbgFlag() procedure and set the _CRTDBG_LEAK_CHECK_DF flag.  With this flag set, you will get a report at the end of your program that lists the errors detected, like times when you wrote past the end of a memory block or memory blocks that were allocated and never deleted.

You can set the flag like

#if _DEBUG
#include <crtdbg.h>
#endif

#if _DEBUG
   int Flg = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
   Flg |= _CRTDBG_LEAK_CHECK_DF;
   _CrtSetDbgFlag(Flg);
#endif

This will give you reports of when errors occur, but won't necessarily help you track down the place where the error occurs.  To help with that you can use the debug allocation procedure _malloc_dbg() to allocate your memory.  This procedure allows you to specify the source code file name and line number of the code requesting the allocation.  This information is then stored with the memory allocated.  Then when an error is dectected with a block, the debug also prints this information which can be invaluable in tracking down the error.  (Just knowing where to start searching makes such a big difference!)


But as C++ programmery, you don't want to use _malloc_dbg(), you want to use "new" and "delete".  No problem.  The basic idea is to overload operator new and delete. with versions that call _malloc_dbg() and _freed_dbg.  _malloc_dbg is like malloc, but allows the file name and line number to be specified.  To make this useful you need to have overloads to operator new (also new[]) that allow the source code file name and line number of the calling code to be passed in.  Now the problem with that is that to use those overloads, the caller would have to use a weird syntax like

int *ptr = new(__FILE__,__LINE__) [100];

that syntax is rather unpleasant and can't be "removed" in a release version.  To get around that we define a macro using #define that allows the overloaded new operators to be called in debug version (passing the file and line number automatically) and allows the regular versions to be called in the release version.

void *
operator new(size_t  Siz,                        // Size of block to allocate.                    //
             char   *FilNam,                     // File name.                                    //
             int     LinNum)                     // Line number.                                  //
{
   return _malloc_dbg(Siz,_NORMAL_BLOCK,FilNam,LinNum);

}

// This overload is needed because A) I have changed
// the standard operator delete to use _free_dbg() and
// B) other code, like from the STL, might allocate memory
// with the regular new (this one) and that memory will be
// deleted with the standard delete, so I have to make this
// new with the delete that I've changed.
void *
operator new [](size_t  Siz)                     // Size of block to allocate.                    //
{
   return _malloc_dbg(Siz,_NORMAL_BLOCK,NULL,123456);
}

void *
operator new [](size_t  Siz,                     // Size of block to allocate.                    //
                char   *FilNam,                  // File name.                                    //
                int     LinNum)                  // Line number.                                  //
{
   return _malloc_dbg(Siz,_NORMAL_BLOCK,FilNam,LinNum);
}



void
operator delete(void *MemPtr,                    // -> memory to free.                            //
                char *FilNam,                    // File name.                                    //
                int   LinNum)                    // Line number.                                  //
{
   _free_dbg(MemPtr,_NORMAL_BLOCK);
}

void
operator delete [](void *MemPtr)                 // -> memory to free.                            //
{
   _free_dbg(MemPtr,_NORMAL_BLOCK);
}
void
operator delete [](void *MemPtr,                 // -> memory to free.                            //
                   char *FilNam,                 // File name.                                    //
                   int   LinNum)                 // Line number.                                  //
{
   _free_dbg(MemPtr,_NORMAL_BLOCK);
}

Final the macros are

#ifdefine _DEBUG
#define QNew    new(__FILE__,__LINE__)
#else
#define QNew    new
#endif
#define QDel    delete

Just use "QNew" everywhee in place of "new" and "QDel"  (for consistency) in place of "delete"  That can be used when allocating arrays (with the [] on the end) and when allocating initialized objects (with the (param,param) at the end.)
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Development

From novice to tech pro — start learning today.