使用源代码行信息进行C ++异常处理

时间:2010-01-05 15:20:43

标签: c++ exception

是否有办法捕获访问冲突等异常并获取有关发生异常的哪一行的信息?这对于调试来说非常有用,特别是对于测试人员而言......

我的环境是VS2008上使用VC ++的Windows

11 个答案:

答案 0 :(得分:3)

访问冲突在C ++术语中不是例外,因此答案通常是“否”。可以肯定的是,您的特定实现可能具有将访问冲突转变为C ++异常的功能 - 您需要指定编译器和放大器。你正在使用的平台。

答案 1 :(得分:3)

如果您确实想要记录代码中抛出的有关C ++异常(AV不是一个)的信息,您可以在异常类型的构造函数中使用宏__FILE____LINE__

答案 2 :(得分:2)

如果使用__catch处理程序捕获SEH异常,则可以在异常时访问线程上下文,然后使用StackWalk64在生成异常的位置转储调用堆栈。请注意,正如我在这里提到的:Printing the stack trace in C++ (MSVC)? StackWalker由Jochen Kalmbach [MVP VC ++]提供,并且在codeproject上可用是最简单的方法。它包含了处理底层StackWalk64 API的所有细节。

或者,您可以使用我在此处提出的相同解决方案:How to catch divide-by-zero error in Visual Studio 2008 C++?将Windows结构化异常转换为C ++异常,并在转换异常时捕获堆栈跟踪,如上所示。这将为您提供C ++异常,其中包含您在C#或Java中获得的堆栈跟踪。

答案 3 :(得分:1)

我不确定为什么测试人员需要知道发生异常的哪一行。

但是,开发人员可能想知道。但更好的方法如下:

  1. 在每个PROGRAM例外中包含有关类和方法的信息。这些是不应该发生的例外情况。

  2. 这应该由您的例外日志输出。你的程序会捕获并记录每个异常,不是吗?如果没有,它应该。

  3. 确保您的方法足够小,以上是足以轻松追踪错误的信息。如果您还需要行信息,那么您的方法太大而且您的例外情况不够具体。

答案 4 :(得分:1)

在MSVC中,您可以将调试器设置为在发生任何异常或类似访问冲突的情况时中断调试 - >异常并检查相应的框。

请注意,访问冲突不是C ++异常,将在不同系统上以不同方式处理。在Windows中,您可以使用结构化异常处理程序捕获它们。在unixy系统中,它通常是核心转储。您通常可以从中获得堆栈跟踪。

答案 5 :(得分:1)

对于msdev / Windows,在开发期间,始终让链接器生成MAP文件。 当Windows抛出访问冲突,并且它是您的代码(而不是库)时,您可以使用该地址来匹配MAP文件中的功能/数据,并在罪犯的几行内。至少,你会知道函数/方法。

答案 6 :(得分:0)

这真是一个编译问题。

如果您想知道编译器是否可能,答案是肯定的。我知道多个Ada编译器为未处理的异常提供回溯,因此显然是可能的。这包括基于gcc的Gnat,因此如果C ++编译器为其异常使用任何相同的工具,那么应该已经支持这样做。

答案 7 :(得分:0)

在unix类型系统上,Access违规会生成SEGV或BUS信号。这通常会导致应用程序进入核心转储。你总是可以编写自己的信号处理程序。从那里你可能会在核心转储之前使用glibc生成堆栈转储。

核心转储通常会在gdb中为您提供所有这些分析。

答案 8 :(得分:0)

我的回答仅涉及Windows。你有很多选择:

不改变您的代码 -

  • 避免捕获异常(至少是您不期望的异常),让您的应用程序崩溃。配置好ol'博士。 watson(drwtsn32.exe)创建崩溃转储,并在调试器中打开该转储。你会得到确切的代码行。
  • Use adPlus(来自windbg安装)监控应用程序的运行,并在抛出异常时创建转储。

从您的代码中,您可以 -

最后,在这个问题上已经提出了很多问题。环顾四周,你会得到更多答案。

答案 9 :(得分:0)

在我工作的一个项目中,使用的异常层次结构的根类在构造函数中捕获了一个callstack,以防稍后在捕获异常后需要调试信息。这是一个不错的主意,虽然如果你正在捕捉和“处理”异常,那么它究竟何时抛出应该不是那么重要。

换句话说,如果你关心这个信息(“谁”扔掉它的上下文),你可能不应该使用异常来报告这个条件,或者你可能不应该在第一名。未捕获的异常会导致崩溃,在抛出异常时给您一个崩溃转储。

答案 10 :(得分:0)

在Windows上,C运行时系统函数_set_se_translator()采用带签名的简单静态函数

void f(int, EXCEPTION_POINTERS*)

你完全不需要这个论点。在f的主体中,抛出你最喜欢的异常。在程序开头附近调用该函数。该文档对于microsoft来说是合理的。

您可以使用此功能执行各种其他操作。

google breakpad项目有很多好处。其中包括使用构建符号和debuginfo dll将崩溃地址转换为文件,行和函数名称的方法。