For some reason the Managed Debugging Assistant CallbackOnCollectedDelegate doesn´t seem to work in Visual Studio 2010, at least not for my sample program.
Instead I encounter the symptom. An unhandled NullReferenceException.
Under normal conditions, running under the debugger with symbol files enabled, you are able to see the call stack of the offending code. But not this time.
Some people know how to read assembly code, and can get a hint of what the program was doing, but Visual Studio 2010, refuses to show any assembler at all.
Let´s debug this in Windbg, a more low level debugger.
Windbg – Black Art Debugging
I start my program, and it halts on an instruction “out dx, al”
The call stack can always be displayed. The stack pointer always have a value. So if it points at a valid address, the instructions can be displayed.
What is important at this moment is not so much what it is doing, but how it got there.
The command “kb” lists the call stack. Whenever a function is entered, not only the parameters are pushed on the stack but also a return address in order to be able to jump back where it was called from.
The return address is the next instruction. If we instead unassemble backwards from the same address, we can see the call that took us into the function.
We can see in the assembler and symbol info, that we wanted to call a function. The function happens to be a callback in managed code (see the last post).
Let us see why the execution generated an exception.
db 0fe07130 dumps the memory where the address to where the function pointer is stored, and it says “4a0b1c00. Since we are dealing with intel architecture the bytes are stored in reverse order. if we would have used the command “dd” we would have seen 001c0b4a instead which is correct.
Dumping the bytes on that adress gives a strange but recurring pattern.
db 001c0b4a ee fe ee fe ee fe ee fe ee
Googling for feeefeee directs us to a wiki page regarding magic number programming
FEEEFEEE Used by Microsoft's HeapFree() to mark freed heap memory
There we have the answer. The code that were about to execute has been freed by the garbage collector.
In defence of MDA
On my sample program this MDA didn’t work in visual studio, but it does work on windbg, running with the environment variable COMPLUS_MDA=1 set.