简体   繁体   English

我应该从P / Invoke不安全代码中得到什么例外?

[英]What exceptions should I expect from P/Invoke unsafe code?

In my solution I've written the following: 在我的解决方案中,我写了以下内容:

[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

In the assumption that CopyFileEx was exported with SetLastError = true parameter of DllImport attribute, do I have a chance to get any unhalted exception here? 假设CopyFileEx是使用DllImport属性的SetLastError = true参数导出的,我是否有机会在此获取任何未定型异常?

I'm specifically interested in non-CLR exceptions which are wrapped in RuntimeWrappedException instance. 我特别感兴趣的是包含在RuntimeWrappedException实例中的非CLR异常。 In C++ "throw 1" is a valid construct. 在C ++中,“throw 1”是一个有效的构造。 So what exceptions should I expect from such P/Invoke calls and where I can obtain such information regarding exceptions (MSDN says nothing regarding exceptions from CopyFileEx)? 那么我应该从这样的P / Invoke调用中获得什么异常,哪些我可以获得有关异常的信息(MSDN对CopyFileEx中的异常没有任何说明)?

If a DLL uses the Win32 structured exception handling system, then any exceptions thrown by the DLL will be translated to OutOfMemoryException , AccessViolationException , NullReferenceException (rarely), or SEHException . 如果DLL使用Win32结构化异常处理系统,则DLL抛出的任何异常都将转换为OutOfMemoryExceptionAccessViolationExceptionNullReferenceException (很少)或SEHException

RuntimeWrappedException is only used when managed C++ throws a non- Exception -derived object. 仅当托管 C ++抛出非Exception -derived对象时,才使用RuntimeWrappedException It is not used for unmanaged DLLs. 它不用于非托管DLL。 If you had a managed C++ DLL that did a throw 1 , then you could catch RuntimeWrappedException . 如果你有一个托管 C ++ DLL,它执行了throw 1 ,那么你可以捕获RuntimeWrappedException

SEHException acts as a catch-all for the unmappable types of SEH exceptions from unmanaged DLLs. SEHException充当来自非托管 DLL的不可映射类型的SEH异常的全能。 This would include any C++ class, or the throw 1 example. 这将包括任何C ++类或throw 1示例。 AFAIK, there is no way to pull the C++-specific exception info out of SEHException , though I'm sure it's hackable if you try hard enough. AFAIK,没有办法从SEHException特定于C ++的异常信息,但我确信如果你努力尝试它是可以SEHException

Note that there are a few DLLs that do not use the Win32 structured exception handling system. 请注意,有一些DLL不使用Win32结构化异常处理系统。 Most notably Cygwin DLLs. 最值得注意的是Cygwin DLL。 In that case, any C++ exception is likely to crash the process or at least your thread. 在这种情况下,任何C ++异常都可能导致进程或至少是您的线程崩溃。 Naturally, all the Windows DLLs (including the one defining CopyFileEx ) do use Win32 structured exception handling, as do any unmanaged DLLs created by Microsoft's C++ compiler. 当然,所有Windows DLL(包括定义CopyFileEx DLL)都使用Win32结构化异常处理,就像Microsoft的C ++编译器创建的任何非托管DLL一样。

Also note that the Win32 API (including CopyFileEx ) does not normally report errors using Win32 structured exceptions; 另请注意,Win32 API(包括CopyFileEx )通常不会使用Win32结构化异常报告错误; they report them via GetLastError . 他们通过GetLastError报告它们。 The only way to get most Win32 functions to throw a Win32 structured exception is to pass it wildly invalid arguments (such as asking it to write into the middle of ntdll.dll ). 让大多数Win32函数抛出Win32结构化异常的唯一方法是传递它非常无效的参数(例如要求它写入ntdll.dll的中间)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM