The following sections describe how to trace attempts to access released memory with the Allocation profiler:
About Accessing Released Memory
Many applications release memory, but attempt to access it later. As a result, the application may crash, raise an exception, cause an access violation error, etc. This situation is known as use after free or premature free, and the remaining reference to the memory is known as a dangling pointer. The situation usually occurs when one part of the application “decides” that it has finished using a memory block and is unaware that another part of the application is still using it.
Sometimes, however, it may be difficult to reveal premature free because of the following peculiarity: when a memory block is deallocated, it is marked as free in a special list, but the actual data remains in memory unless the block is overwritten by other instructions. So, attempts to read data referenced by a dangling pointer may still be successful.
Tracing Use-After-Free Attempts
To track the cases of premature free, you can use the Allocation profiler. When the profiler’s Fill released memory blocks option is enabled, AQTime overwrites the block contents with the
0xDD values. As a result, the application does not read valid data from freed blocks but reads data stored by the Allocation profiler into this block -
0xDD. So, the application will read this value and then use it in further actions.
|Note:||In some cases, system functions may start writing system information to released memory blocks after they have been filled with
For example, if the released block contained a pointer to an object, when the application tries to read its contents and then use it as a pointer, an exception (access violation) will occur and that exception will be reported in the Event View panel.
Tracing Occurred Exceptions
Once an exception occurs, the Event View panel displays its exception code and description, for example, “First chance exception 0xC0000374 Unknown exception occurred at 0x7734E653”. The panel also logs the call stack that led to the exception. In the call stack, the topmost routine is the one where the exception occurred.
If the application was compiled with debug information, then the Editor panel can display the source code for the routine selected in the call stack. Debug info also lets you distinguish routines of the call stack easier. Without it, only the addresses of these routines are displayed. In this case, names are available only for functions that are exported from DLLs. In debug info, routine names are used in their natural format.
However, there is no guarantee that the exception will occur. For example, the data specified by the Allocation profiler can be overwritten once again by the profiled application after the block is released. One more example is when the data stored in the block is used in some calculations. In such cases the application just puts the
0xDD value instead of those that were stored in the block before it was released and no exception occurs.