2014-01-31 27 views
13

我們有一項服務,將在應用程序域級別(通過Log4net)記錄未處理的異常。沒有堆棧跟蹤的異常 - 如何?

我們記錄:

2014年1月28日16:49:19636 ERROR [49] FeedWrapperService - 未處理 System.NullReferenceException:對象不設置爲一個對象的一個​​實例。

此異常沒有堆棧跟蹤。如果沒有對異常對象做一些瘋狂的事情,這怎麼可能?

我們的處理代碼:

AppDomain.CurrentDomain.UnhandledException += LogAnyExceptions; 

private void LogAnyExceptions(object sender, UnhandledExceptionEventArgs e) 
{ 
    log.Error("unhandled", (Exception)e.ExceptionObject); 
    throw (Exception)e.ExceptionObject; 
} 

它發生,我認爲在這裏再投是沒有意義的,因爲在AppDomain將與處理一起反正回落,但我不認爲這會影響我們的情況。

windows應用程序事件查看器也只顯示這個空引用異常並且沒有跟蹤。

我測試了異常處理程序日誌記錄,併成功記錄堆棧跟蹤和任何內部異常。如果它被我們的代碼拋出,我們會看到一個堆棧跟蹤。如果它是由第三方C#庫引發的,那麼我們會再次看到至少有一個方法的堆棧跟蹤(不管它是否是重新拋出的異常)。這裏我們看到一個沒有堆棧跟蹤的託管異常。我不知道這是可能的。

查看反編譯的第三方庫,它與非託管代碼進行通信,並且引發此異常的事件可能位於非託管域中,但如果沒有堆棧跟蹤,這種情況如何導致管理的空引用異常?

此問題的原因是間歇性的。我們已經在生產中運行了這個代碼幾個月,並且看到它只做了一次。這很怪異。

一般的共識是,負責這類問題的系統應該被推送到子進程中,以便我們能夠處理這個問題並安全自動地重啓,但是很高興知道發生了什麼。

編輯從下面包括註釋信息:

我的例外是不是一個標準的重拋,因爲堆棧跟蹤null或空。它沒有其中的重擲方法的名稱。進一步挖掘,可以從序列化信息構造Exception類,並且它看起來像序列化信息可以包含用於堆棧跟蹤的空字符串,並且可能創建而不會導致其他錯誤。我想它可能來自那裏,但我不知道它是如何起源的。

+1

[此線程](http://stackoverflow.com/questions/57383/in-c-how-can-i-rethrow-innerexception-without-losing-stack-trace)可以幫助 – Andrei

+0

手指戳:嘗試檢查['Environment.StackTrace'](http://msdn.microsoft.com/en-us/library/system.environment.stacktrace.aspx),也許內部異常? – Sinatr

+0

@Andrei這是一個有趣的閱讀,但我的例外甚至沒有一個方法在它的堆棧跟蹤,如果這是一個正常的重新拋出,我會有。 進一步挖掘,可以從序列化信息構造Exception類,並且它看起來像序列化信息可以包含空字符串用於堆棧跟蹤而不會導致錯誤。我想它可能來自那裏,但我不知道它是如何起源的。 – Skym

回答

9

如果您收到一個異常但沒有相應的堆棧跟蹤,那麼在某個時候,異常處理程序可能正在評估異常並重新拋出異常。例如,如果你正在做一個throw ex;,你會吃到導致這一點的堆棧軌跡。爲了保持現有的調用堆棧要簡單throw; Throwing exceptions best practices

注意,C#的方式是慣例Java語言,在這裏你都應該throw ex; Java引用的反面:Best Practice: Catching and re-throwing Java Exceptions

1

我喜歡用自定義異常來管理我的異常,如果你的情況是你使用自己的異常,你可以去定義它們並重寫堆棧跟蹤。例如:

public class YourCustomException: Exception 
{ 
    public YourCustomException() : base() { } //constructor 

    public override string StackTrace 
    { 
     get { return " at: my custom stack trace"; } 
    } 
}