Я встречаюсь с ситуацией, когда вызов 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 на второй CloseHandle
выдается SEHException
. Согласно документации для 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?