C++获取异常信息

5
我有一个C++的dll需要调试。由于我使用dll的情况,无法通过调用应用程序进行调试。
因此,我创建了一个try-catch块,在catch中将异常写入文件。
需要调试的行涉及从第三方dll导入的类,因此我无法知道它是什么类型的异常。当我尝试捕获(exception e)时,没有消息被写入文件。所以我尝试了catch(...),它确实触发了一些东西:
使用std::exception::what,唯一被写入文件的是"1"。 使用std::exception::exception,文件接收到了以下代码:"0579EF90"。
是否有任何方法可以检索抛出的异常的有意义信息?
谢谢。

请查看您获得的使用此DLL的许可证,以了解您可以依靠什么样的支持来帮助您行使许可证权利。如果您没有这样的许可证,则需要获取一个。 - Hans Passant
操作系统 - Windows XP 集成开发环境 - Visual Studio 2005 - user228058
catch(...) 无法调用 std::exception::what,而 std::exception::exception 是一个构造函数,与 "codes" 没有任何关系。你问题中的信息是错误的,需要重新编写。此外,你应该通过引用捕获 std::exception - Mooing Duck
5个回答

8
如果您不使用catch(KnownExceptionType ex)并利用您对KnownExceptionType的了解来提取信息,那么您将无法做到这一点。
当您使用catch(...)进行捕获时,您就会陷入困境,您知道您处理了一个异常,但是没有类型信息,您可以做的事情很少。
您处于最糟糕的情况下,即从库中出现的异常,您无法获取有关该异常的任何信息,即使您拥有该库的头文件,该异常类型也不需要在其中定义。

谢谢,您现在有任何其他建议吗? - user228058
在捕获异常时,不要过于依赖异常提供的信息,也许你可以使用调试器,在异常触发之前找到问题所在。 - Arkaitz Jimenez
你所说的“使用调试器”是什么意思?你知道我是否可以在没有调用应用程序的情况下调试C++ dll的方法吗? - user228058
4
为什么你不能使用调用应用程序 - 你没有解释清楚。 - anon
如果调试器无法启动代码,您仍然可以手动启动它,并使调试器附加到程序。 - Mooing Duck

4
如果我理解正确,您已经将问题源头缩小到特定的第三方库调用,但是您不允许在线调试应用程序(我想问为什么?),您的问题是“如何在没有任何异常信息的情况下调试异常”。
答案是,你不能。正如你所观察到的,你只能盲目猜测并希望捕获正确的异常。你也可以使用catch(...), 但那对你来说毫无意义。如果你可以在线调试,你可以设置调试器在抛出异常时中断并查看发生了什么。 我认为正确的答案是联系您已经缩小问题源头的第三方库并询问他们。 抛出异常并允许它跨模块界限传播是非常不好的做法。这让我怀疑它是一个Windows SEH异常,可能是空指针derefer或其他什么问题,并且您正在以一种方式编译,使catch(...)捕获这些异常。

或者它可能是一个 CException* - Mooing Duck

3

也许可以尝试捕获 std::exception & e

  1. std::cout << e.what() << endl;
  2. 看看是否可以将其转换为 std::logic_error 和 std::runtime_error - 这应该会给你一些线索

1
我有点困惑。一方面,你写道catch(std::exception)没有起作用(顺便说一下,你应该使用catch(const std::exception&)),另一方面,你也写道你调用了std::exception::what()。如果一开始没有std::exception,那么你是如何做到这一点的?
无论如何,一旦你捕获到除...之外的任何东西,你可以尝试记录RTTI信息:
#include <typeinfo>

try {
  foreign_code(my_data);
} catch(const some_type& x) {
  std::cerr << "Yikes! Caught exception of type '" 
            << typeid(x).name() 
            << "' with its hand in the cookie jar!\n";
  std::abort();
}

虽然标准并不对 std::type_info::name() 的结果做出任何假设,但大多数(如果不是全部)编译器都会生成一些至少有点用处的代码。

当您在 VS 调试器中时,您还可以设置它,使其在抛出任何异常时停止。这将给您一个堆栈跟踪,从而可能为您提供有关传递给 DLL 的数据可能导致问题的线索。


我不明白它是如何解决问题的,因为他不知道在catch(const some_type& x)中要放什么类型,如果他知道的话,就不需要RTTI信息了。 - Itay Levin
@Itay,这正是我自己感到困惑的地方:user228058写了关于调用std::exception::what()的内容 - 这需要some_type必须是std::exception的后代。 (“如果一开始没有std::exception,你怎么做到的?”)而且在那段代码之上,我明确写道:“[...]一旦你捕获到除...以外的任何异常,[...]”。 - sbi

1

首先,您应该始终通过常量引用捕获异常,换句话说:

catch( const std::exception & ex ) {
  ...
}

不这样做意味着你捕获的异常类型将与实际抛出的异常类型完全相同,这可能会导致丢失异常信息。

然而,似乎你的库抛出的不是派生自std::exception的异常 - 你需要找出它的类型(最好是基础类型)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接