我已经在很多地方(例如这里)读过有关人们在运行时遇到"纯虚方法调用"错误和程序崩溃的问题.这个答案说的是
大多数编译器将这样的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
| 归档时间: |
|
| 查看次数: |
189 次 |
| 最近记录: |