C++虚拟方法引发EXC_BAD_ACCESS(仅当Objective-C++调用时)

C++ virtual method raises EXC_BAD_ACCESS (only if called by Objective-C++)

本文关键字:仅当 Objective-C++ 调用 ACCESS BAD 方法 虚拟 EXC C++      更新时间:2023-10-16

作为一个非常大的代码库的一部分,我有以下内容:

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 changedn";
}

我对C++标准的理解是,这是有效的代码,当doSomething()运行时,FooObjectChanged()会被调用两次而不会出现任何错误。

但我的申请在第二次通话时失败了。(带有segfault,或者更准确地说是iOS上的EXC_BAD_ACCESS

另一个编译器问题是,如果我删除MainStuff::FooObjectChanged()(主体及其声明),我会期望链接器失败,并抱怨抽象类。但编译器不会失败。它链接,然后程序在第一次调用的虚拟函数时崩溃

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

发生了什么事?是什么原因导致了这些问题?FooObserver不是其他任何东西的基类,只是MainStuff的基类。

  1. 检查是否有从MainStuff中的其他基类继承的任何其他纯虚拟函数,并且您没有在MainStuff中重写
  2. Check doSomething是在有效对象上调用的,该对象是活动的并且在作用域内(在调用和处理MainStuff::doSomething()时未被销毁)

这是XCode的一些问题。由于某种原因,它停止了重新编译一些源文件。从DerivedData文件夹中删除所有内容并重新启动XCode后,代码将按照预期进行编译、链接和运行。

我只是遇到了类似的问题,我有多个(2个或多个)C++私有类(即class没有Header),所有类都有完全相同的名称,但在不同的.mm文件中定义了每个都用作std::shared_ptr智能指针的模板参数(在定义它的同一个.mm文件中)。

有时,当调用一个类的virtual方法(使用智能指针的->运算符)时,Clang决定使用另一个类vtable(甚至从未包含其标头),导致二进制文件调用错误的方法地址(以及错误的方法访问的字段,这些字段在类中根本不存在,也称为SIGSEG或BAD_ACCESS)。

我很震惊,因为私有类是一种常见的C++方法,但更改每个私有类的名称(或者至少更改.mm文件的模板参数中使用的名称)确实解决了Objective-C++(或者更确切地说是Clang)的问题。