【问题标题】:C++ virtual method raises EXC_BAD_ACCESS (only if called by Objective-C++)C++ 虚方法引发 EXC_BAD_ACCESS(仅当由 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 搞砸了构建。

标签: c++ inheritance clang abstract-class virtual-functions


【解决方案1】:

我刚遇到类似的问题,我有多个(2 个或更多)C++ private-Classes(即 Class 没有 Header),并且都具有完全相同的名称,但 已定义 在不同的.mm 文件中; 每个都用作模板参数(在同一个 .mm 文件中,在其中定义)std::shared_ptr 智能指针。

有时在调用一个类的virtual 方法(使用智能指针的-&gt; 运算符)时,Clang 决定使用另一个类的vtable(甚至从未包括标题) ,导致二进制调用错误的方法地址(以及错误方法访问的字段,这些字段根本不存在于类中,即 SIGSEG 或 BAD_ACCESS)。

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:
      1. 检查MainStuff中是否有任何其他纯虚函数继承自其他基类,并且您没有在MainStuff中覆盖
      2. 检查 doSomething 是否在有效且在范围内的有效对象上调用(在调用并处理 MainStuff::doSomething() 时未销毁)

      【讨论】:

      • 所有其他纯虚函数在 MainStuff 中都被覆盖了,我在使用它们时没有发现任何问题。 MainStuff 是活跃的并且在范围内。
      • @pramparam 然后尝试重新编译整个代码,应该没问题,从您发布的代码 sn-p 看不出任何问题
      • #1 甚至没有意义;如果没有实现/定义单个“纯虚函数”(例如:无法构造抽象类),任何理智的编译器都会引发编译错误。
      猜你喜欢
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 2017-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-26
      • 2019-06-23
      相关资源
      最近更新 更多