在什么条件下生成纯虚方法存根?

The*_*Vee 13 c++ gcc

我已经在很多地方(例如这里)读过有关人们在运行时遇到"纯虚方法调用"错误和程序崩溃的问题.这个答案说的是

大多数编译器将这样的vtable条目分配给存根,该存根在中止程序之前发出错误.

而且这个人甚至说Itanium ABI指定了那个存根.

问题是:编译器(GCC 6.4.1)在编译时将所有尝试看到这种行为的行为都视为未定义的引用.例如,当从抽象类的构造函数调用纯虚函数时,我收到警告

pure virtual ‘virtual int X::f()’ called from constructor

但同时根本没有生成任何代码,X::f()因此接下来是

undefined reference to 'X::f()'

从链接器和编译失败.这似乎是一种在运行时防止错误的非常简单的方法.在哪种情况下,我的编译器实际上需要生成上述存根?或者它是否足够聪明,足以及早发现所有可能的病理情况?

Sto*_*ica 10

通常它将在构造函数中间接调用.这是一个最小的例子:

#include <iostream>

struct X {
    virtual void foo() = 0;
    void bar() { foo(); }
    X() { bar(); std::cout << "X"; }
};

struct Y : X {
    void foo() override {}
};


int main() {
    Y y;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果调用直接出现在c'tor内,编译器必须静态绑定调用(因此可以为纯虚函数生成有用的错误消息).但是当调用是间接的,来自另一个成员时,它必须是动态调度的.

当然,这个Y部分在构造过程中还没有被构造出来X,所以整个事物在不确定的行为中坍塌了.

Live example - With the stub at work

  • @Steve - 但我们并没有从c'tor调用虚函数.不是直接的.检查我们是否间接调用一个是难以处理的. (3认同)