C++ 虚方法引发 EXC_BAD_ACCESS(仅当由 Objective-C++ 调用时)
Posted
技术标签:
【中文标题】C++ 虚方法引发 EXC_BAD_ACCESS(仅当由 Objective-C++ 调用时)【英文标题】:C++ virtual method raises EXC_BAD_ACCESS (only if called by Objective-C++) 【发布时间】:2014-12-23 09:08:44 【问题描述】:作为一个非常大的代码库的一部分,我有以下内容:
class FooObserver
public:
virtual void FooObjectChanged() = 0;
;
class MainStuff : public FooObserver
public:
/* ... */
void FooObjectChanged();
void doSomething();
;
void MainStuff::doSomething()
this->FooObjectChanged();
FooObserver *o = this;
o->FooObjectChanged();
void MainStuff::FooObjectChanged()
std::cout << "object changed\n";
我对 C++ 标准的理解是,这是有效代码,FooObjectChanged()
会在 doSomething()
运行时被调用两次而不会出现任何错误。
但是我的应用程序在第二次调用时失败了。 (带有段错误,或者更准确地说是 ios 上的 EXC_BAD_ACCESS
)
另一个编译器问题是,如果我删除 MainStuff::FooObjectChanged()
(主体及其声明),我希望链接器会因抱怨抽象类而失败。但编译器不会失败。它链接,然后程序在第一次调用虚函数时崩溃
libc++abi.dylib: Pure virtual function called!
发生了什么事?什么可能导致这些问题? FooObserver
不是其他任何东西的基类,只是 MainStuff
的基类。
【问题讨论】:
构造函数不能是纯虚函数!而且也不应该是虚函数! 你是说构造函数?这在 C++ 中甚至不能是虚拟的,所以它们都不在这个应用程序中。 您是直接还是间接地将其 from 称为构造函数?另外,make clean
看看它是否一直在崩溃。
它不是从构造函数中调用的。但是“make clean”似乎是在正确的方向,我仍在努力确保,但似乎 XCode 搞砸了构建。
【参考方案1】:
我刚遇到类似的问题,我有多个(2 个或更多)C++ private-Classes(即 Class 没有 Header),并且都具有完全相同的名称,但 已定义 在不同的.mm
文件中; 每个都用作模板参数(在同一个 .mm
文件中,在其中定义)std::shared_ptr
智能指针。
有时在调用一个类的virtual
方法(使用智能指针的->
运算符)时,Clang
决定使用另一个类的vtable
(甚至从未包括标题) ,导致二进制调用错误的方法地址(以及错误方法访问的字段,这些字段根本不存在于类中,即 SIGSEG 或 BAD_ACCESS)。
我很震惊,因为私有类是一种常见的 C++ 方法,但是更改每个私有类的名称(或至少,在 .mm
文件的模板参数中使用的名称),确实修复了 Objective-C++ 的(或者更确切地说是 Clang 的)问题。
【讨论】:
【参考方案2】:这原来是 XCode 的一些问题。由于某种原因,它停止重新编译一些源文件。从 DerivedData 文件夹中删除所有内容并重新启动 XCode 后,代码将按我的预期编译、链接和运行。
【讨论】:
【参考方案3】:-
检查
MainStuff
中是否有任何其他纯虚函数继承自其他基类,并且您没有在MainStuff
中覆盖
检查 doSomething 是否在有效且在范围内的有效对象上调用(在调用并处理 MainStuff::doSomething()
时未销毁)
【讨论】:
所有其他纯虚函数在 MainStuff 中都被覆盖了,我在使用它们时没有发现任何问题。 MainStuff 是活跃的并且在范围内。 @pramparam 然后尝试重新编译整个代码,应该没问题,从您发布的代码 sn-p 看不出任何问题 #1 甚至没有意义;如果没有实现/定义单个“纯虚函数”(例如:无法构造抽象类),任何理智的编译器都会引发编译错误。以上是关于C++ 虚方法引发 EXC_BAD_ACCESS(仅当由 Objective-C++ 调用时)的主要内容,如果未能解决你的问题,请参考以下文章