Abstract:
Improving MSVC++ free function.

Created by Peter Kankowski
Last changed
Filed under Win32 programming

Share on social sitesReddit Digg Delicious Buzz Facebook Twitter

Detecting access to freed memory

Visual C++ provides a useful way to find memory leaks in your program. Call the _CrtSetDbgFlag function with _CRTDBG_LEAK_CHECK_DF and _CRTDBG_CHECK_ALWAYS_DF flags, then watch the messages in the Output window. If you define the _CRTDBG_MAP_ALLOC macro, the message will also include the line of code that allocated the leaked block of memory.

Error pattern: using freed memory

There is only one problem with this tool. Consider the program that (erroneously) accesses the memory after it was freed:

char* user_name = (char*)malloc(user_name_len);
...
free(user_name);
...
*user_name = '\0'; // <- error

After the memory block was freed, the CRT free() function fills it with some special value (which is 0xEE in the current version of Visual C++). If the program writes anything to the freed memory, it will overwrite those special bytes. CRT will check the memory block later and detect the problem, although it cannot find which line of code messed with the freed memory.

Also, CRT will not display any message if you attempt to read from the freed memory (but you will get the string of 0xEE bytes: it will look like "îîîîîî" in code page 1252):

char* user_name = (char*)malloc(user_name_len);
...
free(user_name);
...
printf(user_name); // <- error

Solution

If you want to locate the error quickly, without checking every statement that writes to the memory block, you can set the memory pointer to an invalid value after freeing the block:

#ifdef _DEBUG // detect the access to freed memory
#undef free
#define free(p) _free_dbg(p, _NORMAL_BLOCK); *(int*)&p = 0x666;
#endif

Now 'p' points to 0x666, which is an invalid memory address in Win32. This forces your program to crash exactly on the erroneous line of code; the debugger will pop up and show you that line.

(Why choosing 0x666, not zero? When you see the message "access violation reading (or writing) location 0x666", you can feel certain that somebody is playing with the freed memory. At the same time, dereferencing a null pointer is a common bug, which may be caused by many other reasons.)

Peter Kankowski
Peter Kankowski

About the author

Peter is the developer of Aba Search and Replace, a tool for replacing text in multiple files. He likes to program in C with a bit of C++, also in x86 assembly language, Python, and PHP.

Created by Peter Kankowski
Last changed

comments

Your name:


Comment: