使用调用堆栈进行C ++ Visual Studio调试 [英] C++ Visual Studio debugging with call stack

查看:89
本文介绍了使用调用堆栈进行C ++ Visual Studio调试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近开始学习来自C#背景的C ++。我的问题是处理异常的方式。

I have recently began learning C++ coming from a C# background. My problem is with the way exceptions get handled.

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

If I have a nullptr somewhere, resulting in reading from a forbidden location, then I get a nice looking callstack in VS like this:

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

However if I throw my own exception, or an assertion fails, then I do not get any clue as of what went wrong. VS just shows an error window:

A:这对我来说有点不舒服,因为在C#中,两种情况下我都会得到一个堆栈跟踪信息。有没有办法打印堆栈跟踪?还是有任何VS插件可以实现此功能?

A: This is kind of uncomfortable for me as in C# I would get a stacktrace in both case. Is there a way to print the stack trace? Or is there any plugin for VS to achieve this functionality?

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

B: And why is AccessViolationException different than our own thrown exceptions? Why don't we have a stacktrace for assertion failures?

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

C: How bad would it be, to create my own assert function, which would cause an AccessViolationException when assertion fails?

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

Yes, I should have read more carefully that messagebox instead of instantly clicking Abort. My bad.

推荐答案


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

And why is AccessViolationException different than our own thrown exceptions?

由于AV很特殊,它是由处理器本身触发的异常。当它发出不再能够执行代码的信号时引发。就像您想像的那样,这真是一件不幸的事。从AV进行恢复非常非常困难,并且通常不应尝试。您无法再对程序的状态进行推理,您不知道它仅在原始指令地址之外就死了。

Because an AV is special, it is an exception that is triggered by the processor itself. Raised when it signals that is no longer capable of executing code. That's as bad a mishap as you can possibly imagine. Recovering from an AV is very, very difficult and should in general never be attempted. You cannot reason about the state of your program anymore, you don't know where it died beyond just a raw instruction address.

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

Catching and handling an AV is technically possible, you have to use Structured Exception Handling. It requires using the non-standard __try and __except keywords in MSVC++. But you should not do that, since handling an exception requires you to also restore the state of your program to the state it had before you ran the code that failed. Impossible to do reliably since you cannot reason about that state anymore, you don't know what code was skipped by the exception.

您可以在程序中关闭程序有些合理的方法,它需要使用SetUnhandledExceptionFilter()winapi函数。等效于C#中的AppDomain.UnhandledException。当然,所有这些完全是非标准的C ++。 C ++标准规定,符合要求的C ++程序绝不应该调用未定义的行为,并且不指定无论如何都要进行操作。

You can get your program to shutdown in a somewhat reasonable way, it requires using the SetUnhandledExceptionFilter() winapi function. The equivalent of AppDomain.UnhandledException in C#. All of this is entirely non-standard C++ of course. The C++ standard dictates that a conforming C++ program should never invoke undefined behavior and does not specify what should happen when you do anyway.

否则,这是编程关闭的直接结果。金属。托管代码中有一个 lot 对策,可以防止程序进入这种状态。这些对策不是免费提供的,本机C ++关心使代码尽可能快地运行。丢失诊断信息是折衷方案的一部分。不要调用未定义的行为。

This is otherwise a direct consequence of programming close to the metal. There are a lot of counter-measures in managed code to prevent a program from ever getting into a state like this. These counter-measure do not come for free, native C++ cares about making code run as fast as possible. Losing diagnostics is part of that trade-off. Don't invoke undefined behavior.

这篇关于使用调用堆栈进行C ++ Visual Studio调试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆