Over a million developers have joined DZone.

MDA: Callback On Garbage Collected Delegate

DZone's Guide to

MDA: Callback On Garbage Collected Delegate

· ·
Free Resource

One day I’m going to write a long, detailed post about an incredible tool called Managed Debugging Assistants (MDAs). But today is not that day. Instead, I would like to ignite your interest in MDAs by showing you how they immediately make obvious a non-trivial debugging scenario.

Oren writes:

[…] if you run [this code] on a background thread and continue to do additional operations […] it will crash, sometimes with a null reference exception, sometimes with attempt to write to protected memory, etc.

There is a very subtle bug here, can you figure out what it is?

Luckily, this bug is not subtle enough to escape automatic detection. But first things first. I wrote a simple test case that is fairly similar in spirit to the bug Oren is referring to. Then, I ran the executable and received the following exception:

An access violation, all right, but what’s the precise location that caused the problem? The DoWork method is a P/Invoke call, but is it responsible for the memory corruption?

Opening the application’s crash dump yields the following call stack for the crash:

0:000> kn
NativeDll!DoWork+0x41 [nativedll.cpp @ 10]

0:000> u 00120b92
00120b92 0000            add     byte ptr [eax],al
00120b94 0000            add     byte ptr [eax],al
00120b96 0000            add     byte ptr [eax],al
00120b98 9f              lahf
00120b99 f79d6a286a00    neg     dword ptr [ebp+6A286Ah]
00120b9f 1c01            sbb     al,1
00120ba1 0000            add     byte ptr [eax],al
00120ba3 0000            add     byte ptr [eax],al

The function invoked by DoWork looks like a random bunch of assembly instructions… It’s not immediately evident from what we’ve seen so far where the culprit lies. However, let’s see what happens if we run the application from within Visual Studio, with the debugger attached:

Visual Studio hands us the error on a silver platter—or, to be specific, the CallbackOnCollectedDelegate MDA hands us this bug. This is an automatic diagnostic tool that pops up in the middle of your debugging session and shows you the error of your ways. It appears that the delegate must be kept alive until the underlying P/Invoke call is done—if the delegate is garbage collected and a call is attempted through it from unmanaged code, havoc ensues.

CallbackOnGarbageDelegate has many other MDA friends lurking in the Visual Studio “Exceptions” dialog. You can enable and disable MDAs during your Visual Studio debugging session, or in advance using a special configuration file.

As I said, I’m looking forward to writing a couple more posts on MDAs. Until then, you might find the following resources useful:


Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}