【发布时间】:2021-09-27 16:27:30
【问题描述】:
我想知道当给定一个与对象的真实内存位置不同的基类指针时,删除运算符如何计算出需要释放的内存位置。
我想在我自己的自定义分配器/释放器中复制此行为。
考虑以下层次结构:
struct A
{
unsigned a;
virtual ~A() { }
};
struct B
{
unsigned b;
virtual ~B() { }
};
struct C : public A, public B
{
unsigned c;
};
我想分配一个 C 类型的对象并通过 B 类型的指针删除它。据我所知,这是对 operator delete 的有效使用,它在 Linux/GCC 下工作:
C* c = new C;
B* b = c;
delete b;
有趣的是,指针'b'和'c'实际上指向不同的地址,因为对象在内存中的布局方式不同,而删除操作符“知道”如何找到并释放正确的内存位置。
我知道,一般来说,在给定基类指针Find out the size of a polymorphic object 的情况下,不可能找到多态对象的大小。我怀疑通常也无法找到对象的真实内存位置。
注意事项:
- 我的问题与 new[] 和 delete[] 的工作方式无关。我对单个对象分配案例感兴趣。 How does delete[] "know" the size of the operand array?.
- 我也不关心如何调用析构函数。我对内存本身的释放感兴趣。 How 'delete' works when I delete a pointer of base class
- 我使用 -fno-rtti 和 -fno-exceptions 进行了测试,因此 G++ 不应访问运行时类型信息。
【问题讨论】:
-
简短回答:它是定义的实现,除了标准说符合标准的编译器必须支持这一点。然而,我的猜测是 G++ 使用 vtable 跳转到内部销毁逻辑的某些部分,这将正常工作。
-
不过,看看一些实现会很有趣。 (在某种程度上,C 中的
malloc/free是相似的,我相信方法是在从malloc返回的指针“之前”保留一些空间以进行内务处理。) -
虽然,我没有得到
b != c.. 有不同的变量,但都“指向”同一个对象(内存),不是吗? (我不使用 C++,所以我失去了它的魔力)。 -
@jrok 哦,是的。在多重继承的情况下,父指针和基指针可能不会指向同一个地方。
-
我建议尝试 g++ 中的 -fdump-class-hierarchy 选项,它提供了对 vtable 结构的大量洞察,在这种情况下使用它。您需要通过 c++filt 运行输出。
标签: c++ memory-management g++