2011-04-11 98 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

相關問題