开发者

CallbackOnCollectedDelegate - what happens when no debugger is attached?

I'm trying to diagnose a client crash which we cannot reproduce thus far in a debug environment.

I am trying to determine whether a CallbackOnCollectedDelegate MDA notification (resulting from third-party code) would have otherwise resulted in a crash if the debugger was not attached.

So, the question is, could the problem in the third-party code that is causing callbacks on collected delegates be the cause of this behaviour - an MDA when debugging and a client-crash when not?

Info on this MDA: http:/开发者_运维技巧/msdn.microsoft.com/en-us/library/43yky316(v=vs.80).aspx


If you got that MDA warning then you definitely repro-ed the problem. Yes, that will be a hard crash without a debugger, the native code will bomb when it makes the callback. The stub that marshals the call from native to managed code is no longer there. The likelihood for an AVE is high, albeit never 100% guaranteed since the memory location might refer to a valid address when it got re-used after the stub was collected. Random code execution is then the failure mode. Either outcome is excessively ugly and hard to diagnose, never let it come this far.

It is caused by not storing a reference to the delegate that you passed to the native code. Or not keeping the object that stores the reference alive, same thing. The garbage collector cannot see and does not know that the native code is using the stub. In fact, the CLR destroys the stub when the delegate gets collected, that is how it manages the memory allocations for stubs.

It is up to you to ensure this cannot happen. The most often correct solution is to store the delegate object reference in a private static variable. Only set it back to null when you explicitly told the native code to no longer make callbacks. Never setting it back to null is quite common. Also add a test to ensure it is null before you assign the variable, throw an InvalidOperationException if it is not. If you need an extra level of indirection then use GCHandle.Alloc(Object). Same recipe, don't call Free() until you know it is safe.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜