free()方法分配的内存安全吗?

Is it safe to free() memory allocated by new?

本文关键字:内存 安全 分配 方法 free      更新时间:2023-10-16

我正在编写一个c++库,其中一个函数返回一个(新分配的)指向双精度数组的指针。API声明释放内存是调用者的责任。

然而,该c++库过去是用C实现的,并且所讨论的函数用malloc()分配内存。它还假设调用者将使用free()释放该内存。

可以安全地将malloc()呼叫替换为new呼叫吗?如果我这样做,现有的客户端代码(使用free())会中断吗?到目前为止,我所能找到的是free()的官方文档,其中指出

如果ptr没有指向用[malloc, calloc或realloc]分配的内存块,它会导致未定义的行为。

但是我相信这是在c++出现自己的分配操作符之前写的

你必须匹配mallocfreenewdelete的调用。

您不允许将mallocfreenewdelete混合使用。c++标准草案参考了C99标准,如果我们去看c++标准草案20.6.13 C库它说(强调我的未来):

内容与标准C库头文件stdlib.h相同,有以下更改:

:

函数calloc()、malloc()和realloc()不尝试通过调用::operator来分配存储空间新()(18.6).

:

函数free()不尝试通过调用::operator delete()来释放存储空间。参见:ISO C Clause 7.11.2。

和包括其他更改,其中没有一个声明我们可以在new分配的内容上使用free。所以7.20.3.2 部分C99标准草案中的自由函数仍然是正确的参考,它说:

否则,如果实参与先前由calloc、malloc或realloc函数返回的指针不匹配,或者如果空间已经通过调用free或realloc释放,行为是未定义的

正如你现在所听到的,你不能把它们混在一起。

请记住,在c++中,通常会动态分配许多相对较小的临时对象(例如,很容易编写像my_string + ' ' + your_string + 'n'这样的代码),而在C中,内存分配通常更深思熟虑,通常具有更大的平均分配大小和更长的生命周期(更有可能有人直接使用malloc(strlen(my_string) + strlen(your_string) + 3)来获得结果,而没有任何临时缓冲区)。出于这个原因,一些c++库将针对大量小的瞬态对象进行优化。例如,它们可能使用malloc()获取三个16k块,然后分别将每个块用于最多16、32和64字节的固定大小请求。如果在这种情况下调用delete,它不会释放任何东西—它只是将16k缓冲区中的特定条目返回给c++库自由列表。如果你调用free(),而指针恰好指向16k缓冲区中的第一个元素,你会意外地释放所有元素;如果它不是第一个你有未定义的行为(但一些实现像Visual c++显然仍然释放块给指针在其中的任何地方)。

所以-真的,真的不要这么做。

即使它表面上在你当前的系统上工作,它也是一个等待爆炸的炸弹。不同的运行时行为(基于不同的输入、线程竞争条件等)可能导致以后的失败。使用不同的优化标志、编译器版本、操作系统等进行编译都可能随时破坏它。

标准库应该提供一个释放函数来转发到正确的函数。

除了其他人已经说过的(没有兼容性保证)之外,还有一种可能性,即库链接到与您的程序不同的C库,因此在从它们接收到的指针上调用free()会将其传递给错误的释放函数,即使函数名称是正确的。

必须使用delete操作符来释放由new操作符分配的内存。

malloc()分配内存并将第一个块的地址发送给分配的指针变量,在new的情况下,它分配内存并返回地址。当你使用malloc()函数时,我们应该使用delete函数,当你在new函数的帮助下分配内存时,free()函数的使用是舒适的。当使用malloc()函数时,我们应该使用相应的realloc(),calloc(),delete()函数,类似地,当使用new()函数时,使用相应的free()函数。