将删除与基类指针一起使用会导致内存泄漏吗?

时间:2010-01-20 10:32:28

标签: c++ memory-management memory-leaks

鉴于两个类只有原始数据类型而没有自定义析构函数/解除分配器。 C ++规范是否保证它将以正确的大小解除分配?

struct A { int foo; };
struct B: public A { int bar[100000]; };
A *a = (A*)new B;
delete a;

我想知道我是否需要写一个空的virtual dtor?

我尝试过g ++和vc ++ 2008,它们不会导致泄漏。但我想知道C ++标准中的正确内容。

5 个答案:

答案 0 :(得分:24)

除非基类析构函数是虚拟的,否则它是未定义的行为。见5.3.5 / 4:

  

如果[删除运算符]的操作数的静态类型与其动态类型不同,则静态类型应为操作数的动态类型的基类,静态类型应具有虚拟析构函数或行为未定义

答案 1 :(得分:16)

根据C ++标准,你所拥有的是未定义的行为 - 这可能表现为泄漏,它可能不会,为了你的代码是正确的,你需要一个虚拟的析构函数。

此外,您不需要(A *)演员。每当你发现自己在C ++中使用C风格的强制转换时,你可以相当确定它是不必要的,或者你的代码是错误的。

答案 2 :(得分:1)

这是未定义的行为 - 也许一切都很好,也许出现了问题。要么不这样做,要么为基类提供虚拟析构函数。

在大多数实现中,这不会泄漏 - 类中没有堆分配的成员函数,因此完成delete时唯一需要的是释放内存。解除分配内存只使用对象的地址,仅此而已,堆完成所有其余的工作。

答案 3 :(得分:1)

对于原始数据,我相信你很好。在这种情况下,您可能合法地不想承担v-table的费用。 否则,绝对是首选。

答案 4 :(得分:0)

它将以正确的大小释放,因为要释放的大小是您获得的堆内存区域的属性(没有传递给free()的大小 - 就像函数一样!)。

然而,没有人被召唤。如果'B'定义了析构函数或包含任何具有非平凡析构函数的成员,则不会调用它们,从而导致潜在的内存泄漏。但是,在您的代码示例中并非如此。