升級到 dotnet core 之後 HandleProcessCorruptedStateExceptions 無法接住異常
技術標籤:dotnetcorec#C#dotnetdotnet core
這是 dotnet core 的破壞性改動之一,在 dotnet framework 裡面,可以使用 HandleProcessCorruptedStateExceptionsAttribute 接住非託管層丟擲的異常,如 C++ 異常等。但是這個功能在 dotnet core 下存在行為的變更,從 .NET Core 1.0 開始,損壞程序狀態異常無法由託管程式碼進行處理。 公共語言執行時不會將損壞程序狀態異常傳遞給託管程式碼
如果邏輯程式碼完全使用 C# 實現,那麼應用程式可以稱為是安全的。這裡的安全指的是記憶體安全。這是 dotnet 的一個優勢,在於異常處理上,和 C++ 等的異常處理不同的是,很少會有異常能讓整個程式閃退。可以很方便在應用程式裡面接住軟體執行異常,然後通過各個方法讓軟體繼續執行
但如果 C# 呼叫了 C++ 的庫,那就不好玩了,這就意味著如果 C++ 的庫如果實現不夠好的話,那麼這個庫是能帶著整個應用程式閃退的。而有趣的是,其實我到現在還沒遇到幾個團隊寫出的 C++ 庫是穩定的,基本上通過我的 DUMP 分析可以看到,每多加一個 C++ 庫,軟體的穩定性就下降一半。好在,有一些 C++ 庫丟擲來的異常,咱勉強還是能接住的,至少不會讓整個應用程式就閃退了
接住 C++ 異常的其中一個方法就是通過 HandleProcessCorruptedStateExceptions 特性,在方法上面標記 HandleProcessCorruptedStateExceptions 特性,此時在方法裡面使用 try catch 是可以接住大部分的 C++ 異常的,如 System.AccessViolationException 異常
請看下面程式碼
[HandleProcessCorruptedStateExceptions]
static void Main(string[] args)
{
try
{
Console.WriteLine(HeederajiYeafalludall());
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
[DllImport("BeyajaydahifallChecheecaifelwarlerenel.dll")]
static extern Int16 HeederajiYeafalludall();
上面程式碼的 HeederajiYeafalludall 方法是由 BeyajaydahifallChecheecaifelwarlerenel.dll 提供的,這是一個由 C++ 寫的庫,在這裡面的實現將會出現越界
extern "C" __declspec(dllexport) int HeederajiYeafalludall()
{
int* p = (int*)123;
while (true)
{
*p = 123;
p++;
}
return 123;
}
在標記了 HandleProcessCorruptedStateExceptionsAttribute 特性之後,將可以看到斷點能進入到 catch 程式碼裡,而且程式不會閃退
但是這個機制在 dotnet core 就跑不起來了,根據 從 .NET Framework 到 .NET Core 的中斷性變更 文件,可以看到在 .NET Core 1.0 開始,損壞程序狀態異常無法由託管程式碼進行處理,將上面的 C# 程式碼切換到 dotnet core 下執行,此時將會發現不會進入到 catch 的程式碼,應用程式將會退出
大家可以嘗試使用我放在 github 的程式碼進行測試,切換框架為 .NET Framework 和 .NET Core 比較這裡的行為
本作品採用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名林德熙(包含連結:http://blog.csdn.net/lindexi_gd ),不得用於商業目的,基於本文修改後的作品務必以相同的許可釋出。如有任何疑問,請與我聯絡。