为什么虚拟方法生成对_sbrk的未定义引用?
Why virtual method generates undefined reference to _sbrk?
这编译得很优雅:
class dummy {
};
这抱怨对_sbrk的未定义引用:
class dummy {
virtual ~dummy();
};
为什么虚拟方法生成对_sbrk
的未定义引用?
我曾经认为vtable
是静态分配的,不需要malloc
.
编译器:arm-none-eabi-gcc 8.0.0
最近newlib
。用-fno-rtti -fno-exceptions -fno-unwind-tables
编译。
测试程序(boot
像main
(:
class base {
public:
virtual ~base();
};
class dummy : public base {
public:
~dummy();
};
base::~base() {
__BKPT();
}
dummy::~dummy() {
__BKPT();
}
extern "C" void _sbrk() {
__BKPT();
}
void boot() {
for(;;) {
base b;
dummy d;
}
return 0;
}
派生类可以有自己的删除运算符。此功能很少使用 - 根据我的经验,几乎从未使用过。虚拟析构函数允许在使用删除表达式时调用正确的运算符 delete(delete p
(。
编译器肯定生成了一个虚拟析构函数与删除,它调用特定于类的运算符 delete,在几乎所有情况下,它恰好是全局运算符 delete (::operator delete
(,但它也可以被类中定义的本地运算符覆盖。
由于从未使用过delete
(对于该特定类型(,因此永远不会调用带删除的析构函数自动生成的虚拟函数,但仍在 vtable 中引用该函数。除非你有适当的编译器和链接器支持,否则每个虚拟函数都会在 vtable 中引用,并且 vtable 至少在类的构造函数中使用,因此任何构造的对象都需要该类的每个虚函数。
如果您有适当的链接器支持,则只能引入已命名的虚拟函数;其他 vtable 条目可以为 null,因为它们永远不会被引用。
编辑:标准报价
来自[class.dtor]/12:
在定义虚拟析构函数时(包括 隐式定义(,非数组释放函数是 确定为表达式
delete this
出现在析构函数类的非虚拟析构函数(请参见 [expr.delete](。 如果查找失败或解除分配函数已删除 定义,程序格式不正确。[ 注意:这可确保 与对象的动态类型对应的释放函数 可用于删除表达式 ([class.free](。— 尾注 ]
"虚拟析构函数"...确定为"非虚拟析构函数"包含表达式是一个可能难以解码的措辞:既然析构函数是虚拟的,我们为什么要谈论虚拟析构函数?(我不得不多次阅读上面的标准文本。
另一种查看方式是,就可能的实现而言(一些实现曾经正是这样做的(:
每个析构函数实际上都deallocate
一个布尔参数,编译器添加代码:
if (deallocate)
delete this;
就在析构函数主体结束之前,所有析构函数都使用false
参数调用,但在调用delete
运算符时,除了完整对象的一个。
我几乎可以肯定_sbrk被调用是因为您对虚函数的使用已经拉入了代码路径,以引发对"纯虚函数"调用的异常。
在你的地图文件中四处看看什么在叫_sbrk,什么在叫它,等等,直到你找到根。
请参阅这篇文章以获取更多信息:声明抽象类(纯虚拟方法(大大增加了二进制大小
附言:虚拟表不需要动态内存分配
我曾经认为 vtable 是静态分配的,不需要 malloc。
不确定你从哪里得到这个假设:
- 不能保证如何实现 vtables,标准也没有说动态调度需要使用 vtables 来实现。这只是最常见的方法。
- 在您的问题中,我缺少任何证据,证明
_sbrk
实际上是因为析构函数正在被拉入virtual
而且,我真的不明白这个问题的目的:如果你想使用虚拟方法,无论如何你都需要有动态内存分配函数。
- 编译C++时未定义的引用
- vscode g++链路故障:体系结构x86_64的未定义符号
- 如何修复此错误:未定义对"距离(浮点数,浮点数,浮点数,浮点数,浮点数)"的引用
- 我的项目不会像"undefined reference to `grpc::g_core_codegen_interface'"那样使用未定义的引用错误进行编译
- 不知道某个东西是否被忽略会引入未定义的行为吗
- 对C宏的未定义引用,但在定义它时会出现重新定义错误
- 未定义的引用在哪里
- 编译时的 CImg 库返回对"__imp_SetDIBitsToDevice"的未定义引用
- 对Py_Initialize()的未定义引用
- c++11评估顺序(未定义的行为)
- 使用mysql c++连接器的未定义引用
- 从python调用openMP共享库时,未定义opnMP函数
- 在 Mac 上使用 CMAKE 将 FFTW 和 FFTWPP 链接到项目中时未定义的符号
- Cmake 链接问题:未定义对 Button::mousePressEvent(QGraphicsSceneMouseE
- 未定义的引用 .. 使用 OpenCV 编译 C++ 代码时,从命令行
- 具有外部"c"和程序集的未定义函数
- 此增量后语句是否会导致未定义的行为?
- 尝试调用 .h 文件中定义的变量时出现变量未定义错误
- 在C++中使用内联方法时出现未定义的符号错误
- 对 Scalar ::Scalar() 的未定义引用