Какие исключения следует ожидать от небезопасного кода P / Invoke? - PullRequest
3 голосов
/ 25 июля 2010

В моем решении я написал следующее:

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern unsafe bool CopyFileEx(string lpExistingFileName,  
 string lpNewFileName, CopyProgressRoutine lpProgressRoutine, IntPtr lpData,  
 Boolean* pbCancel,    CopyFileFlags dwCopyFlags);

...

bool result;

unsafe{
  result = CopyFileEx(sourceFile, targetFile, null, IntPtr.Zero,  
                      null /* pointer */, 0);
}

if(!result)
    Win32Exception exc = new Win32Exception(Marshal.GetLastWin32Error()); 
// parameter could be omitted according to Win32Exception constructor 
// implementation

Если предположить, что CopyFileEx был экспортирован с параметром SetLastError = true атрибута DllImport, могу ли я получить здесь какое-либо неисключенное исключение?

Меня особенно интересуют не-CLR исключения, которые заключены в экземпляр RuntimeWrappedException. В C ++ «throw 1» является допустимой конструкцией. Итак, каких исключений мне следует ожидать от таких вызовов P / Invoke и где я могу получить такую ​​информацию об исключениях (MSDN ничего не говорит об исключениях из CopyFileEx)?

1 Ответ

6 голосов
/ 25 июля 2010

Если в DLL используется структурированная система обработки исключений Win32, любые исключения, выданные DLL, будут преобразованы в OutOfMemoryException, AccessViolationException, NullReferenceException (редко) или SEHException.

RuntimeWrappedException используется только тогда, когда managed C ++ генерирует объект, не являющийся Exception. Он не используется для неуправляемых библиотек DLL. Если у вас была управляемая C ++ DLL, которая выполняла throw 1, то вы могли бы поймать RuntimeWrappedException.

SEHException действует как универсальное средство для не отображаемых типов исключений SEH из неуправляемых DLL. Это может включать любой класс C ++ или пример throw 1. AFAIK, нет способа вытащить информацию об исключениях, специфичных для C ++, из SEHException, хотя я уверен, что это можно взломать, если вы попытаетесь достаточно усердно.

Обратите внимание, что есть несколько библиотек DLL, которые не используют систему обработки структурированных исключений Win32. В частности, библиотеки Cygwin. В этом случае любое исключение C ++ может привести к сбою процесса или, по крайней мере, вашего потока. Естественно, все библиотеки DLL Windows (включая определяющую CopyFileEx) используют структурированную обработку исключений Win32, как и любые неуправляемые библиотеки DLL, созданные компилятором Microsoft C ++.

Также обратите внимание, что Win32 API (включая CopyFileEx) обычно не сообщает об ошибках, используя структурированные исключения Win32; они сообщают о них через GetLastError. Единственный способ заставить большинство функций Win32 выдать структурированное исключение Win32 - передать ему недопустимые аргументы (например, попросить записать его в середине ntdll.dll).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...