如果我在使用new或delete时使用free或malloc,会有什么结果?

4
这是一个编译错误还是运行时错误?以下代码可以编译!
class Base{
void g();
void h();
};

int main()
{
    Base* p = new Base();
    free(p);
return 0;
}

但是如果我像这样声明Base类,它就无法使用虚函数进行编译:
class Base{
virtual void g();
void h();
};

无论函数是否为虚函数,下面的代码都可以一直编译。
class Base{
void g();
void h();
};

int main()
{
    Base* p = (Base*)malloc(sizeof(Base));
    delete p;
return 0;
}

9
结果是该程序没有定义的行为。 - avakar
@avakar,为什么不将其作为答案发布? - Peter Alexander
1
@Poita - 显然他想让得到这些积分;-) - user180247
你应该使用reinterpret_cast,而不是你所使用的c-style转换。 - Joe D
3个回答

11

未定义的结果,加上malloc()不调用构造函数,free()不调用析构函数。


1
由于行为未定义,如果您使用new分配的指针将其传递给free(),则free()可能会调用析构函数。我同意“它不会”这一点,因为我怀疑在任何实现中都会这样做。 - Steve Jessop
是的,但您也面临这样一个问题,即new分配的内存不能保证与free兼容。同样适用于malloc和delete。 - Joe D

3
正如注释所说-程序的行为是未定义的。
如果您在“new”中使用“free”,则不会调用析构函数。这通常导致内存和资源泄漏。
如果您在“malloc”中使用“delete”,则不会获得构造函数调用,因此您的对象未初始化。这可能导致各种错误,例如在调用析构函数时出现错误。
如下面的注释所示,在非POD类型(例如具有虚拟方法的类和使用虚拟继承的类)中存在需要初始化的内容,即使不明显需要构造函数初始化也是如此。如果您malloc一个对象然后调用虚拟方法,则最有可能的结果是您的程序将崩溃。
到目前为止,如果您的所有类型都是POD(Plain Old Data),您可能会很幸运,但这在很大程度上取决于您的编译器-不能保证“malloc”和“new”使用相同的堆,因此您可能会在某些编译器上遇到堆破坏和崩溃。
简而言之-不要这样做。

你说得没错,但在实际应用中,我从未遇到过一个编译器不使用malloc/free来分配全局new/malloc的内存。当然,这并不能完全依赖。 - zebrabox
POD类型不能有虚函数,因此第二个不是POD类型。 - James McNellis
@James - 我在描述一般原则。正如你所说,虚函数是类型不是POD的明显证据,而使用malloc的明显问题是虚指针没有初始化,因此对后期绑定方法的调用将会崩溃。 - user180247

1

这是一种未定义行为。这意味着任何事情都可能发生——程序可能会成功,也可能会崩溃,甚至可能在一个看似无关紧要的代码片段中默默地失败并在以后崩溃,或者甚至可能抹掉您的硬盘。

任何事情都可能发生,因为您正在做C++标准不允许的事情。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接