How to replace the global operator new and delete in an MFC application (debug only)

I have avoided trying to do anything with the new operator for many years, due to my feeling that it is a quagmire on Windows (especially using MFC). Not to mention the fact that if someone has a very good reason for communicating with the global (or even class) new and remote, it should not.

However, I have an unpleasant memory error, and I would really like to track it. I receive messages from a CRT debug allocator indicating that previously freed memory was overwritten. This message is displayed only during the subsequent allocation call, when it tries to reuse the block (I believe this is how it works).

Due to the piece of code in question, the error message and the corruption point are very unrelated. All I know is “somewhere rewriting some memory somewhere that had previously been freed with a single null byte.” (I figured this out using the debugger and watching the memory referenced by the heap of debugging on several different runs).

Having exhausted the obvious ideas about where the criminal could be, I was left with an attempt to do something more rigorous. It occurred to me that it would be ideal if I could make every freed block become a page without access to memory, so that the writer would immediately catch the processor MMC! A little later, and I found a person who realized something in this direction:

http://www.codeproject.com/Articles/38340/Immediate-memory-corruption-detection

His code is buried under a ton of inventive wheel code, but extracting the basic concept was pretty simple, and I did it.

Now the problem is that MFC redfines new as DEBUG_NEW, and then additionally defines many debugging interfaces up to CRT. In addition, it defines the global operator new and delete. Therefore, with regard to C ++, the “user” is trying to replace the global operator new and delete twice, and therefore, I get a linker error with the effect symbol already indicated.

Looking around the Internet and so on, I see some promising articles, but none of them ultimately has anything good to say about replacing the global new / delete operator for MFC.

How to replace global new and delete operators correctly
Is it possible to replace the memory allocator in the debug build of an MFC application?

I already know:

  • MFC / CRT already provides rich debugging tools for memory allocation.

Well, he provides what he provides - for example, the message that made me roll along this path in the first place. Now I know that corruption is happening, but this terribly weak sauce!

What I would like to provide is a dedicated allocation (or even just a guarded release). This is certainly possible using a lot of virtual address space and placing each allocation in isolation, which is terribly wasteful for memory. Well, yes, I don’t see the downside when this is debug only code, useful for special moments like now.

So, I am desperately looking for solutions for the following

  • Make the compiler co-op with my global new / delete operator, despite the CRT / MFC provided.
  • Find another way to bind the MFC / CRT _heap_alloc_dbg chain to the lower limit when using my own code instead of them to highlight in the perpendicular (i.e. I will allocate through OS VirtualAlloc / VirtualFree to provide memory for new and / or malloc).

Does anyone know answers or good reading articles that can shed light on how this can be achieved?

Other ideas:

  • Replace CRT new / delete at runtime using thunk technology.
  • Is there any other approach completely ?!

Further research:

  • This article is pretty cool ... it gives me the ability to fix global new / delete statements at runtime. However, as the article points out, this is a little hacky (however, since I only need it for debugging collections, this is not a big deal) http://zeuxcg.blogspot.com/2009/03/fighting-against-crt-heap-and- winning.html
    • So, although this is achieved by what I want (a mechanism for replacing CRT memory allocation functions), this implementation is quite far from obsolete, and so far my attempts to get it working have run into a lot of problems. I think that it is too hacked into the version originally created for it, and only for the relatively simple use of the console (i.e. C, even C ++, and discarding most of the debugging functions provided by Microsoft CRT). Therefore, although a super-cool idea, which, ultimately, would be worth many hours of effort to work with the current VS2010 dev studio, and therefore not worth it (for me).
  • There seems to be a known version of this idea: http://en.wikipedia.org/wiki/Electric_Fence Unfortunately, even the Windows port I found is http://code.google.com/p/electric-fence-win32 / cannot replace CRT correctly, but asks you to change all of your source code in order to gain access to the distribution code of the heap of the electric fence. :(

Update 3/5/2012:

  • And now I found that Windows already provides an Electric Fence implementation, available through the GFLAGS debugging tool http://support.microsoft.com/kb/286470 This can also be enabled from the external to the application under test. This is essentially the same technology that I was interested in, and has functions in the DUMA project (branch of the electric fence - http://duma.sourceforge.net/
+6
source share
1 answer

The MSVCRT debug heap is actually pretty good and has some useful features you can use, such as a breakpoint on the nth distribution, etc.

http://msdn.microsoft.com/en-us/library/974tc9t1(v=VS.80).aspx

Among other things, you can insert a selection hook that displays debugging information, etc., which you can use to debug this problem.

http://msdn.microsoft.com/en-us/library/z2zscsc2(v=vs.80).aspx

In your case, all you really need to do is print out the address and file and line of each selection. Then, when you experience a damaged block, find a block whose address immediately precedes it, which will almost certainly be what is torn off. You can use the memory view in the Visual Studio debugger to look at the damaged memory address and see previous blocks. This should tell you everything you need to know in order to find out when it was allocated.

The debug heap also has a numerical distribution identifier on each selected block and can break on the nth! therefore, if you can get reasonably compatible reprogramming, the same number block will be damaged every time, then you can use the "break on nth" function to get the full call stack in the time that has been allocated.

You can also find _CrtCheckMemory to find out if damage has occurred before. Just name it periodically, and as soon as you have an error enclosed in brackets (the error did not happen in one, happened in the other), move them closer and closer.

+4
source

Source: https://habr.com/ru/post/914682/


All Articles