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

C++ C++;使用源代码行信息处理异常,c++,exception,C++,Exception,是否有一种方法可以捕获访问冲突之类的异常,并获取异常发生在哪一行的信息?这对于调试来说是非常好的,特别是对于测试人员 我的环境是VS2008上的Windows和VC++我不确定为什么测试人员需要知道发生异常的行 不过,开发人员可能想知道。但更好的方法是: 在每个程序异常中包含有关类和方法的信息。这些都是不应该发生的例外情况 这应该由任何记录异常的日志输出。你的程序会捕获并记录每个异常,不是吗?如果没有,它应该这样做 确保您的方法足够小,以使上面的信息足以轻松跟踪bug。如果您还需要行信息,那么您

是否有一种方法可以捕获访问冲突之类的异常,并获取异常发生在哪一行的信息?这对于调试来说是非常好的,特别是对于测试人员


我的环境是VS2008上的Windows和VC++

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

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

  • 在每个程序异常中包含有关类和方法的信息。这些都是不应该发生的例外情况

  • 这应该由任何记录异常的日志输出。你的程序会捕获并记录每个异常,不是吗?如果没有,它应该这样做

  • 确保您的方法足够小,以使上面的信息足以轻松跟踪bug。如果您还需要行信息,那么您的方法太大,并且您的异常不够具体


  • 这确实是一个编译器问题


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

    < P>访问违反在C++术语中也不是例外,所以答案一般是“否”。当然,您的具体实现可能具有将访问违规转换为C++异常的特性——您需要指定您使用的编译器和平台。p> 在unix类型的系统上,访问冲突会生成SEGV或总线信号。这通常会导致应用程序核心转储。您可以编写自己的信号处理程序。在此基础上,您可能会在堆芯转储之前使用glibc生成堆栈转储


    在gdb中,核心转储通常为wasy分析提供所有这些信息

    在MSVC中,您可以将调试器设置为在出现任何异常或访问冲突等情况时中断,然后转到debug->Exceptions并选中相应的框


    注意,访问违规不是C++异常,在不同系统上会有不同的处理。在Windows中,您可以使用结构化异常处理程序捕获它们。在unixy系统中,通常会进行堆芯转储。您通常可以从中获得stacktrace。

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

    不改变你的代码-

    • 避免捕捉异常(至少是您不期望的异常),让您的应用程序崩溃。配置好的ol'dr.watson(drwtsn32.exe)以创建崩溃转储,并在调试器中打开该转储。你会在那里得到准确的代码行
    • (来自windbg安装)监视应用程序的运行,并在引发异常时创建转储
    在代码中,您可以-

    • 当抛出结构化异常时,可以轻松地遍历堆栈。例如,见
    • 在抛出C++异常时使用堆栈。

    最后,关于这个问题,这里提出了很多问题。环顾四周,你会得到额外的答案。

    如果你真的想记录关于C++异常的信息(AV不是从你的代码中抛出),你可以在宏的开发中使用宏:<代码>始终让链接器生成映射文件。
    当Windows抛出访问冲突时,这是您的代码(不是库),您可以使用该地址匹配映射文件中的函数/数据,并在违规者的几行之内。至少,您会知道函数/方法。

    在我参与的一个项目中,使用的异常层次结构的根类在构造函数中捕获了一个调用堆栈,以防在捕获异常后稍后调试时需要该信息。这是一个不错的主意,尽管如果您正在捕获并“处理”异常,那么抛出异常的确切时间应该不会太重要


    换句话说,如果您关心此信息(“谁”抛出它的上下文),则可能不应该使用异常来报告此情况,或者可能不应该首先捕获异常。未捕获的异常会导致崩溃,在抛出异常时会导致崩溃转储。

    如果使用捕获处理程序捕获SEH异常,则可以在异常发生时访问线程上下文,然后使用StackWalk64在生成异常时转储调用堆栈。请注意,正如我在这里提到的:由Jochen Kalmbach[MVP VC++]编写并在codeproject上提供可能是最简单的方法。它总结了处理底层StackWalk64 API的所有细节


    可选的,您可以使用我在这里提出的相同的解决方案:将Windows结构化异常转换为C++异常,并捕获堆栈跟踪,如上面所示,在您翻译异常的位置。这将给你一个C++异常,它有一个堆栈跟踪,比如你在C或java中得到的。p> 在windows上,C运行时系统函数_set_se_translator()采用带有签名的简单静态函数

    void f(int, EXCEPTION_POINTERS*)
    
    这两个论点你都不需要。在f的主体中,抛出您最喜欢的异常。在程序开始时调用函数。该文档对microsoft来说是合理的

    你可以用这个函数做各种各样的附加工作


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

    您在什么样的环境中操作?正在使用什么编译器?很抱歉响应太晚,我的环境是VS 2008和vc++,请确保在调用中使用这些宏