c# - 异常从非托管代码传播到托管代码?

标签 c# c++ exception

我有一大块非托管 C++ 代码,正在 C# 项目上重用。非托管 C++ 代码包装在托管 C++ 代码层内,该代码与 C# 代码进行交互。目前,非托管 C++ 代码使用assert(false) 来引发严重错误。由于assert()写入stderr并且我的项目是一个GUI程序,我认为断言打印输出不会显示。我正在考虑用 throw new exception(...) 替换assert(false),然后在 C# GUI 层捕获并显示异常。我的问题是:

1) 用Exception() 替换assert() 是个好主意吗?如果不是为什么?

2) 如果在非托管 C++ 代码中引发异常,它们是否会正确传播到托管 C++,然后传播到 C# 代码(堆栈跟踪完整且正确)?

谢谢

最佳答案

1) Is replacing assert() with exception() a good idea? if not why?

assert是一个调试工具。它将在发布版本中评估为无操作,并且不打算用作错误处理工具。在 C++ 中实现基于异常的错误报告系统是很自然的事情。

2) If exceptions are thrown inside unmanaged C++ code, will they propagate properly to the managed C++ and then to C# code (with the stack trace intact and correct)?

native 代码中抛出的 C++ 异常将转换为 SEHException从非托管代码移动到托管代码时。 C++ 异常可以在 native 代码、C++/CLI 互操作层或托管代码中处理。 (人类可读)调用堆栈信息在 native 代码中不可用。


有关混合模式环境中异常处理的背景信息:

C++ 异常(在 Microsoft 的 C++ 编译器中实现)以及 CLR 中的异常都构建在 SEH 异常之上。 Structured Exception Handling是 Windows 中内置的一项服务,任何可以与 C 接口(interface)的环境都可以使用该服务。共享相同的基础使异常能够从托管代码无缝传播到非托管代码,反之亦然。

所有 SEH 异常都携带存储在 EXCEPTION_RECORD 中的相同信息。 。 ExceptionAddress 成员用作构造堆栈跟踪的入口点。托管程序集包含足够的元数据来构造人类可读的堆栈跟踪。另一方面, native 可执行镜像则不然。虽然可以生成堆栈跟踪(例如使用 StackWalk64 ),但除非相应的调试信息 (.pdb) 可用,否则不会包含任何符号信息。


堆栈跟踪的替代方案:

虽然堆栈跟踪可能会给您一些引发异常的提示,但它不包含任何对调试有用的信息,例如参数和局部变量。另一种选择是编写一个小型转储。 MiniDumpWriteDump是一个非常强大的工具,可以让您非常精细地控制应包含哪些数据。非常好的介绍可以在Effective Minidumps - Part 1找到和 Effective Minidumps - Part 2 。小型转储可以加载到调试器(例如 Visual Studio 或 WinDBG)中并进行分析。通过匹配的调试符号(您应该将其添加到任何版本的源代码控制系统中),您将获得一个非常有效的基础设施来分析问题。根据可用的小型转储信息,您将获得所有线程的调用堆栈、传递给函数的参数、局部变量的内容、加载和卸载的模块等。

关于c# - 异常从非托管代码传播到托管代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18724205/

相关文章:

c++ - boost::noncopyable_::noncopyable 模拟移动构造函数/赋值

Java:数组索引越界

java - 当主类尝试调用另一个类的私有(private)方法时如何抛出异常?

c# - GMail + C# + Web.Config : Send Mail Works Programmatically, 使用 Web.Config 值引发异常

python - Cython C++ 示例失败,为什么?

C++ 字符数组作用域

java - DRY 用于异常包装

c# - SignalR 作为游戏服务器

c# - 如何使用c#将Excel中的一行格式复制到另一行

c# - 在itextsharp中为pdfpcell添加圆形颜色边框