1

我正在尝试接收有关我在托管 (.net/c#) 的 catch 块中在本机 (c++/win32) 中抛出的异常的数据。

例如,在 c++ 中,我们可以:

void MyFunc()
{
    const char* data = "my exception info";
    ULONG_PTR args[1] { data };
    RaiseException(0,0,1,args);
}

这个函数可以通过 C# 中的 P/Invoke 调用:

[DLLImport("MyLib.dll")]
extern public static void MyFunc();

static void Main()
{
    try { MyFunc(); }
    catch(SEHException seh)
    {
        // Where is my exception info? :(
    }
}

SEHException不包含来自导入的 DLL 函数的字符串

SEHException.ErrorCode 似乎总是 E_FAIL,但无论如何我都想编组比 int 更丰富的数据。

我是否遗漏了什么,或者是否有另一种方法可以通过异常获取此字符串数据?

目的是通过设置本机过滤器(如 SetUnhandledExceptionFilter,FYI),使用本机堆栈跟踪重新引发本机异常。

4

1 回答 1

1

SEH 异常通常没有参数,而且数据方式也很少。实际上,您所能得到的只是异常发生时的数字异常代码处理器状态(包括指令指针和堆栈指针)

C++ 异常处理使用的是用于启动处理程序的 SEH 异常,但 C++ 异常对象实际上存储在其他地方(详细信息在编译器及其运行时库内部)。从另一种语言访问它几乎是不可能的。甚至其他 C++ 编译器也有一段糟糕的时光。所有 C++ 异常共享一个异常代码。

像您正在做的那样手动调用RaiseException确实允许您存储异常参数,就像操作系统异常一样EXCEPTION_ACCESS_VIOLATIONEXCEPTION_IN_PAGE_ERROR请参阅EXCEPTION_RECORDMSDN。使用 Microsoft C++ 编译器,您可以通过GetExceptionInformation. 而且您当然不应该将 C++ 对象与std::stringwith组合在一起RaiseException——您错过了 C++ 编译器为这些对象的生命周期管理添加的额外魔法。不过,将字符串数据作为const char*字符串文字传递应该没问题。

然后您将面临在 .NET 中检索此信息的问题。即使是有限的(异常代码、上下文和记录,没有 C++ 对象)信息,我认为您也无法从 .NETSEHException对象中获得这些信息。您看到的原因E_FAIL是文档中此注释的结果,而不是异常代码。

SEHException 类处理从非托管代码引发但尚未映射到另一个 .NET Framework 异常的 SEH 错误。SEHException 类还响应 HRESULT E_FAIL,其值为 0x80004005。

于 2014-09-03T17:50:29.123 回答