C# 代码未捕获 SEHExceptions
C# code not catching SEHExceptions
我有一个 C# 应用程序调用一个托管的 C++ DLL,该 DLL 故意访问无效地址;我在我的 C++ 项目中启用了 SEH Exceptions
,我在我的 C++ 代码中添加了一个 _se_translator_function
,我还在 SIGSEGV
发生时添加了一个信号处理程序。使用来自纯本机测试的 C++ 代码,一切正常,但是当我从 .net 应用程序调用我的 C++ 代码时,应用程序崩溃并显示:
Unhandled Exception: System.AccessViolationException: Attempted to
read or write protected memory. This is often an indication that other
memory is corrupt.
at K.killnative() in c:\users\ebascon\documents\visual studio 2013\projects\consoleapplication3\consoleapplication4\source.cpp:line 32
这是我的 C# 控制台应用程序:
namespace ConsoleApplication3 {
class Program {
static void Main(string[] args) {
try {
var k = new NativeKiller();
k.kill();
}
catch (Exception ex) {
Console.WriteLine("Catching " + ex);
}
}
}
}
这是调用的 C++/CLI 代码:
void MXXExceptionTranslator(unsigned int, struct _EXCEPTION_POINTERS*)
{
throw std::exception("Crash happens");
}
void killnative() {
try {
_set_se_translator(MXXExceptionTranslator);
signal(SIGSEGV, [](int) {
puts("Exception");
exit(-1);
});
int* p = reinterpret_cast<int*>(0xDEADBEEF);
printf("%d\n", *p);
}
catch (...) { //Removing this catch does not change anything
puts("Doing nothing");
}
}
public ref class NativeKiller {
public:
void kill() {
killnative();
}
};
你认为我做错了什么?在我现实世界的问题中,我需要这个 C++/CLI 进程(这是一个与遗留应用程序的桥梁)来记录错误消息并优雅地死去,而不是弹出 "The program stopped working" window.
提前致谢,
埃内斯托
这是一个很好的问题,它可以帮助您发现您没有正确构建代码。 C++/CLI 编译器非常强大,几乎太 强大,几乎可以将任何本机代码翻译成 IL。与 C# 编译器生成的 IL 完全相同。并且它在运行时被视为相同,抖动在运行时将其转换为机器代码。
这通常不是您真正想要的。本机 C 或 C++ 代码应该由编译器直接翻译成机器代码。 _set_se_translator() 的 MSDN 文章对此做了很好的警告:
When using _set_se_translator from managed code (code compiled with /clr) or mixed native and managed code, be aware that the translator affects exceptions generated in native code only. Any managed exceptions generated in managed code (such as when raising System::Exception) are not routed through the translator function.
通常的落坑方式是在自己的源文件或库项目中单独编译native代码。但更容易的是利用 C++/CLI 编译器的能力在单个源文件中在 IL 和机器代码生成之间来回动态切换。修复:
#pragma managed(push, off)
void MXXExceptionTranslator(unsigned int, struct _EXCEPTION_POINTERS*) { ... }
void killnative() { ... }
#pragma managed(pop)
public ref class NativeKiller { ... }
现在您会看到异常转换器工作正常。
我有一个 C# 应用程序调用一个托管的 C++ DLL,该 DLL 故意访问无效地址;我在我的 C++ 项目中启用了 SEH Exceptions
,我在我的 C++ 代码中添加了一个 _se_translator_function
,我还在 SIGSEGV
发生时添加了一个信号处理程序。使用来自纯本机测试的 C++ 代码,一切正常,但是当我从 .net 应用程序调用我的 C++ 代码时,应用程序崩溃并显示:
Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at K.killnative() in c:\users\ebascon\documents\visual studio 2013\projects\consoleapplication3\consoleapplication4\source.cpp:line 32
这是我的 C# 控制台应用程序:
namespace ConsoleApplication3 {
class Program {
static void Main(string[] args) {
try {
var k = new NativeKiller();
k.kill();
}
catch (Exception ex) {
Console.WriteLine("Catching " + ex);
}
}
}
}
这是调用的 C++/CLI 代码:
void MXXExceptionTranslator(unsigned int, struct _EXCEPTION_POINTERS*)
{
throw std::exception("Crash happens");
}
void killnative() {
try {
_set_se_translator(MXXExceptionTranslator);
signal(SIGSEGV, [](int) {
puts("Exception");
exit(-1);
});
int* p = reinterpret_cast<int*>(0xDEADBEEF);
printf("%d\n", *p);
}
catch (...) { //Removing this catch does not change anything
puts("Doing nothing");
}
}
public ref class NativeKiller {
public:
void kill() {
killnative();
}
};
你认为我做错了什么?在我现实世界的问题中,我需要这个 C++/CLI 进程(这是一个与遗留应用程序的桥梁)来记录错误消息并优雅地死去,而不是弹出 "The program stopped working" window.
提前致谢,
埃内斯托
这是一个很好的问题,它可以帮助您发现您没有正确构建代码。 C++/CLI 编译器非常强大,几乎太 强大,几乎可以将任何本机代码翻译成 IL。与 C# 编译器生成的 IL 完全相同。并且它在运行时被视为相同,抖动在运行时将其转换为机器代码。
这通常不是您真正想要的。本机 C 或 C++ 代码应该由编译器直接翻译成机器代码。 _set_se_translator() 的 MSDN 文章对此做了很好的警告:
When using _set_se_translator from managed code (code compiled with /clr) or mixed native and managed code, be aware that the translator affects exceptions generated in native code only. Any managed exceptions generated in managed code (such as when raising System::Exception) are not routed through the translator function.
通常的落坑方式是在自己的源文件或库项目中单独编译native代码。但更容易的是利用 C++/CLI 编译器的能力在单个源文件中在 IL 和机器代码生成之间来回动态切换。修复:
#pragma managed(push, off)
void MXXExceptionTranslator(unsigned int, struct _EXCEPTION_POINTERS*) { ... }
void killnative() { ... }
#pragma managed(pop)
public ref class NativeKiller { ... }
现在您会看到异常转换器工作正常。