Я сталкиваюсь с ситуацией, когда вызов PInvoke для CloseHandle
вызывает SEHException
в приложении .NET 4 при запуске под отладчиком. В отличие от других, которые сталкивались с аналогичными проблемами при переходе с 3.5 на 4 , меня это не особо беспокоит, и я уже обнаружил проблему (сторонняя библиотека, вызывающая CloseHandle
дважды для одного и того же дескриптора) , Тем не менее, я озадачен тем, почему такое поведение не происходит в приложении .NET 3.5.
Следующий небольшой, но полный пример демонстрирует поведение, с которым я сталкиваюсь (протестировано на XP SP3 и Win 7 x64, всегда скомпилировано как x86):
class Program
{
static void Main(string[] args)
{
try
{
var hFileMapping = CreateFileMapping(new IntPtr(-1), IntPtr.Zero, 0x04 /* read write */, 0, 0x1000, null);
CloseHandle(hFileMapping);
CloseHandle(hFileMapping);
Console.WriteLine("No exception");
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadKey();
}
[DllImport("kernel32", SetLastError = true)]
static extern IntPtr CreateFileMapping(IntPtr hFile, IntPtr lpAttributes, int flProtect, int dwMaximumSizeHigh, int dwMaximumSizeLow, string lpName);
[DllImport("kernel32", SetLastError = true)]
static extern bool CloseHandle(IntPtr handle);
}
При запуске в качестве приложения .NET 4, SEHException
генерируется во втором CloseHandle
. Согласно документации для CloseHandle
, это ожидаемое поведение:
Если приложение работает под отладчиком, функция
бросить исключение, если оно получает либо значение дескриптора, которое не
допустимое или псевдо-дескриптор значение. Это может случиться, если закрыть ручку
дважды, или если вы вызываете CloseHandle для дескриптора, возвращенного
Функция FindFirstFile вместо вызова функции FindClose.
Однако при компиляции в качестве приложения .NET 3.5 (или CLR 2.0) при втором вызове CloseHandle
не возникает исключений, и выводится сообщение "No exception"
.
Согласно этой статье обновленный CLR, выпущенный для .NET 4, имеет несколько другое поведение по умолчанию с низкоуровневыми исключениями, которые могут повредить состояние процесса. Однако, насколько я понимаю из этой статьи, ничего не упоминалось о предыдущем поведении CLR, из-за которого исключение было бы полностью проигнорировано.
Почему приложение .NET 3.5 (или CLR 2.0) не демонстрирует документированное поведение CloseHandle
, присутствующее в .NET 4?