这个问题在这里已有答案:
我正在研究一个C ++库,其中一个函数返回一个(新分配的)指向一个双精度数组的指针。 API声明调用者有责任释放内存。
但是,C ++库曾经在C中实现,并且有问题的函数使用malloc()
分配内存。它还假设调用者将使用free()
释放该内存。
我可以通过调用malloc()
安全地替换对new
的调用吗?现有的客户端代码(如果我这样做,使用free()
会破坏吗?到目前为止我能找到的是free()
的官方文档,其中说明了
如果ptr没有指向使用[malloc,calloc或realloc]分配的内存块,则会导致未定义的行为。
但我相信这是在C ++与自己的分配运算符一起出现之前编写的。
你不允许将malloc
和free
与new
和delete
混合搭配,C ++标准草案回到C99标准,如果我们去draft C++ standard部分20.6.13
C库,它说(强调我的前进):
内容与标准C库头stdlib.h相同,但有以下更改:
和:
calloc(),malloc()和realloc()函数不会通过调用:: operator new()(18.6)来尝试分配存储。
和:
函数free()不会尝试通过调用:: operator delete()来释放存储空间。另见:ISO C条款7.11.2。
并包含其他更改,其中没有一项表明我们可以在free
分配的内容上使用new
。部分7.20.3.2
C99标准草案中的自由函数仍然是适当的参考,它说:
否则,如果参数与之前由calloc,malloc或realloc函数返回的指针不匹配,或者如果通过调用free或realloc释放了空间,则行为未定义。
你必须将malloc
与free
和new
与delete
的调用相匹配。混合/匹配它们不是一种选择。
正如你现在所听到的,你不能混合它们。
请记住,在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()
分配内存并将第一个块的地址发送到指定的指针变量,在新的情况下,它分配内存并返回地址。这是一个约定,当你使用malloc()
函数时,我们应该使用delete函数,当你在新函数的帮助下分配内存free()
函数的使用是舒适的。当malloc()
it是一个惯例,我们应该使用相应的realloc(),calloc(),delete()
函数,类似地,当你使用new()
函数时,使用相应的free()
function。