异常从非托管代码传播到托管代码? 我有一块非托管C++代码,我在C项目中重用。非托管C++代码被封装在一个托管C++代码层中,它与C代码兼容。现在,非托管C++代码使用AsSturt(false)来提高临界错误。由于assert()写入stderr,而我的项目是一个GUI程序,因此我认为不会显示assert打印输出。我正在考虑用throw new exception(…)替换assert(false),然后在C#GUI层捕获并显示异常。我的问题是:

异常从非托管代码传播到托管代码? 我有一块非托管C++代码,我在C项目中重用。非托管C++代码被封装在一个托管C++代码层中,它与C代码兼容。现在,非托管C++代码使用AsSturt(false)来提高临界错误。由于assert()写入stderr,而我的项目是一个GUI程序,因此我认为不会显示assert打印输出。我正在考虑用throw new exception(…)替换assert(false),然后在C#GUI层捕获并显示异常。我的问题是:,c#,c++,exception,C#,C++,Exception,1) 用exception()替换assert()是个好主意吗?如果不是,为什么 < P > 2)如果在非托管C++代码中抛出异常,它们会正确地传播到托管C++,然后传播到C代码(堆栈跟踪完整和正确)?< /P> 谢谢 1) 用exception()替换assert()是个好主意吗?如果不是,为什么 是一个调试工具。它将在发布版本中评估为无操作,并不打算用作错误处理工具。在C++中实现基于异常的错误报告系统是很自然的事情。 < P > 2)如果在非托管C++代码中抛出异常,它们会正确地传播到托管

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

< P > 2)如果在非托管C++代码中抛出异常,它们会正确地传播到托管C++,然后传播到C代码(堆栈跟踪完整和正确)?< /P> 谢谢

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

是一个调试工具。它将在发布版本中评估为无操作,并不打算用作错误处理工具。在C++中实现基于异常的错误报告系统是很自然的事情。 < P > 2)如果在非托管C++代码中抛出异常,它们会正确地传播到托管C++,然后传播到C代码(堆栈跟踪完整和正确)?< /P> 从非托管代码转换为托管代码时,本机代码中抛出的C++异常将转换为s。C++异常可以在本地代码中处理,在C++/CLI互操作层或托管代码中处理。(人类可读)调用堆栈信息在本机代码中不可用


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

C++异常(如微软的C++编译器中的实现)以及CLR中的异常都是在SEH异常之上建立的。是一个内置到Windows中的服务,它可以被任何与C. Sharing接口的环境所消耗。同一个基础使异常能够无缝地从托管代码传递到非托管代码,反之亦然。 所有SEH异常都包含存储在数据库中的相同信息。

ExceptionAddress
成员用作构建堆栈跟踪的入口点。托管程序集包含足够的元数据来构造人类可读的堆栈跟踪。另一方面,本机可执行映像则不是。虽然可以生成堆栈跟踪(例如使用),但除非相应的调试信息(.pdb)可用,否则不会包含任何符号信息


堆栈跟踪的替代方案:


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

首先,将其用作错误处理程序是个坏主意。如果定义了
NDEBUG
,则它无效
assert
将写入控制台应用程序中的
stderr
,并在GUI应用程序中调用
MessageBox
。这将是可见的(无论如何在调试版本中)。@llnspectable是的,我知道在发布版本中编译assert。我有点同意。我最关心的是在发生错误时获取堆栈跟踪。assert只写入GUI程序没有的stderr,这对我来说是一个更大的缺点。assert()的默认行为是调用调试器中断。别弄糟了。@Hans The不同意你的说法。@l非常感谢你提供的详细信息!我特别喜欢小型垃圾场的建议。我一定会调查的。关于assert的一个问题:根据Microsoft文档,如果从基于Windows的应用程序调用assert,它将在messagebox中显示消息。但是,如果从链接到基于Windows的应用程序的DLL的深层调用assert,messagebox还会被使用吗?@llnspectable-最好在致命错误发生时创建一个小型转储,还是让它抛出一个异常并在最高级别捕获它,然后在那里执行小型转储?后者的优点是我不必在整个代码库中散布minidump调用。只是想知道这样做是否有任何缺点。@Thomas
assert
实现对CRT中声明的(未记录的)
\uuuuuApp\uType
变量求值,因此它将始终选择正确的输出方法。当引发异常时,您应该始终立即编写一个小型转储,以获取相关的调用堆栈。为此,您需要安装一个SEH异常过滤器(这将为您获得
MiniDumpWriteDump
所需的
exception\u记录)。这使您可以在一个地方处理所有异常—无需在整个代码中散布调用。这并不是什么小事,你可能应该问一个关于这个主题的新问题。MSDN链接: