2011-04-11 43 views
2

我试图诊断一个客户端崩溃,我们无法在调试环境中复制到目前为止。CallbackOnCollectedDelegate - 未连接调试器时会发生什么?

我想确定一个CallbackOnCollectedDelegate MDA通知(由第三方代码产生)是否会在调试器未连接时导致崩溃。

所以,问题是,第三方代码中导致收集委托回调的问题可能是这种行为的原因 - 调试时是MDA还是客户崩溃?

信息在此MDA:http://msdn.microsoft.com/en-us/library/43yky316(v=vs.80).aspx

回答

3

如果你得到了MDA警告,那么你肯定是摄制-ED的问题。是的,如果没有调试器,这将是一次严重的崩溃,本地代码在进行回调时会弹出。将调用从本机编组到托管代码的存根不再存在。 AVE的可能性很高,尽管从未100%保证,因为内存位置在收集存根后重新使用时可能指的是有效地址。随机代码执行就是失败模式。无论哪种结果都非常难看,难以诊断,绝不会让它出现这么远。

这是由于没有存储对传递给本机代码的委托的引用。或者不保留存储引用的对象仍然存在,同样的事情。垃圾回收器看不到,也不知道本机代码正在使用存根。实际上,当委托收集时,CLR销毁存根,这就是它如何管理存根分配的存根。

这是由你来确保这不可能发生。最经常正确的解决方案是将代理对象引用存储在专用static变量中。当您明确告诉本机代码不再进行回调时,仅将其设置回null。永远不要将它设置回null是很常见的。在分配变量之前,还要添加一个测试以确保它为空,如果不是,则抛出InvalidOperationException。如果您需要额外的间接级别,请使用GCHandle.Alloc(Object)。相同的配方,不要打电话给Free(),直到你知道它是安全的。

+0

太好了,那个特殊的崩溃是在第三方.NET封装器中用于第四方JBIG2解码器。我一直在等待供应商在相同的代码中修复访问冲突的一年。 :( – 2011-04-11 12:59:09

+0

另外,我已经在该代码周围有一个catch(AccessViolationException);理论上,MDA告诉我会发生访问冲突,任何想法为什么它不会抛出AVE? – 2011-04-11 14:44:17

+0

当本机代码回调,你不能用托管代码来捕捉它。 – 2011-04-11 22:08:12

相关问题