如何追踪“libc ++ abi.dylib:称为纯虚函数!”在Xcode中

时间:2015-12-02 19:51:32

标签: c++ xcode macos

我有一个多线程OS X应用程序,它使用C ++,Objective-C和Swift的混合。

当我的应用程序关闭时,我在Xcode调试器窗口中看到了这一点:

libc++abi.dylib: Pure virtual function called!

我知道这个错误通常是由在C ++类构造函数或析构函数中调用虚函数引起的。

有没有一种简单的方法可以找到它的位置?通过“简单”,我的意思是“不分析每个构造函数的每一行的调用树和每个具有虚函数的类的析构函数”。

我没有看到堆栈跟踪。打印此消息时,调试器不会暂停程序。从我的应用代表的applicationDidTerminate方法记录的消息在此消息之前。

我尝试在“所有异常”上设置断点但不幸的是,断点经常受到使用大量异常的代码的影响。是否有其他符号可以放置断点?

2 个答案:

答案 0 :(得分:6)

C ++标准库定义了一些实现低级语言/库功能的“ABI”函数。 libc++有一个很好的文档来描述它们here

其中一个是__cxa_pure_virtual,当程序以某种方式调用纯虚函数时调用它。因此,如果您在那里设置断点,您应该能够找到发生的位置。

通常,当您从构造函数或析构函数中调用虚函数时,会发生纯虚函数调用,而vtable处于中间状态。有关详细信息,请参阅this answer

答案 1 :(得分:1)

首先,它很可能是在析构函数中调用纯虚函数而不是构造函数(不保证,但很可能)。

如果在调用纯虚函数时编译器正在生成异常,那么您可以通过使用set_terminate()设置自己的终止处理程序来捕获它(例如解释here) 。然后,您可以在终止处理程序中设置断点,以确切了解代码到达该点的方式。

如果在调用纯虚函数时编译器没有生成异常(更可能的情况),那么您可以尝试添加自己的虚拟类来帮助缩小发生违规调用的位置。只需让这些虚拟类在其析构函数中打印一些内容,并确保它们有时会被删除,以便在事情发生时缩小范围。例如,在main()函数的最开头放置一个,如果看到其消息打印,则在删除静态对象时会发生违规调用,因为该虚拟对象将是main()返回之前删除的最后一个对象。你可以通过添加这样的虚拟类来做类似的事情,作为你可以修改的其他类的第一个数据成员,但你需要知道被删除的对象导致违规的纯虚函数调用。

最后,如果它很有用,你实际上可以为纯虚函数提供一个实现,实际上可以调用它们(是的,这是合法的C ++)。如果您知道正在调用的确切纯虚函数,那么您可以为它提供一个实现,并在其中放置一个断点来捕获堆栈跟踪。这依赖于您完全知道被调用的纯虚函数,而您的问题表明这可能不为人所知。