【问题标题】:C++ Visual Studio debugging with call stack使用调用堆栈进行 C++ Visual Studio 调试
【发布时间】:2013-09-27 04:23:12
【问题描述】:

我最近开始从 C# 背景开始学习 C++。我的问题在于处理异常的方式。

如果我在某处有一个nullptr,导致从一个禁止的位置读取,那么我会在 VS 中得到一个漂亮的调用堆栈,如下所示:

但是,如果我抛出自己的异常,或者断言失败,那么我就不会得到任何关于哪里出错的线索。 VS 只是显示一个错误窗口:

答:这对我来说有点不舒服,因为在 C# 中我会在这两种情况下得到堆栈跟踪。有没有办法打印堆栈跟踪?或者有没有VS的插件可以实现这个功能?

B: 为什么 AccessViolationException 与我们自己抛出的异常不同?为什么我们没有断言失败的堆栈跟踪?

C:创建自己的断言函数会有多糟糕,当断言失败时会导致 AccessViolationException?

EDIT1:是的,我应该更仔细地阅读该消息框,而不是立即单击中止。我的错。

【问题讨论】:

  • 在断言消息框上按“重试”,您应该会看到一个漂亮的对话框,其中提供了调试代码的选项,包括查看调用堆栈。对于异常:您也可以这样做:您可以在抛出异常时打开中断,它位于设置中的某个位置。
  • 是的,谢谢戴夫,这应该足够了。但是仍然有人可以回答我在 B 点提出的问题吗?

标签: c++ visual-studio exception callstack


【解决方案1】:

为什么 AccessViolationException 与我们自己抛出的异常不同?

因为 AV 是特殊的,它是由处理器本身触发的异常。当它发出不再能够执行代码的信号时引发。这是你可以想象的最糟糕的事故。从 AV 中恢复非常非常困难,通常不应尝试。您无法再推断程序的状态,除了原始指令地址之外,您不知道它在哪里死亡。

捕获和处理 AV 在技术上是可行的,您必须使用结构化异常处理。它需要在 MSVC++ 中使用非标准的 __try 和 __except 关键字。但是您不应该这样做,因为处理异常还需要您将程序的状态恢复到运行失败代码之前的状态。不可能可靠地执行,因为您无法再推断该状态,您不知道异常跳过了哪些代码。

您可以通过某种合理的方式关闭您的程序,这需要使用 SetUnhandledExceptionFilter() winapi 函数。相当于 C# 中的 AppDomain.UnhandledException。当然,所有这些都完全是非标准的 C++。 C++ 标准规定,符合标准的 C++ 程序绝不应该调用未定义的行为,并且没有指定无论如何应该发生什么。

否则,这是靠近金属编程的直接后果。在托管代码中有很多对策可以防止程序进入这样的状态。这些对策不是免费的,原生 C++ 关心的是让代码尽可能快地运行。失去诊断是这种权衡的一部分。不要调用未定义的行为。

【讨论】:

    猜你喜欢
    • 2012-11-10
    • 2016-03-16
    • 2010-11-09
    • 2018-12-09
    • 2014-09-11
    • 2019-10-31
    • 1970-01-01
    • 1970-01-01
    • 2019-06-11
    相关资源
    最近更新 更多