我想知道使用malloc和free的正确/标准方法是什么。是否需要设置指针空后自由?基本上,以下两种方式哪一种是正确的?
double* myPtr = (double*)malloc(sizeof(double)*5);
.....
free(myPtr);
或
double* myPtr = (double*)malloc(sizeof(double)*5);
.....
free(myPtr);
myPtr = NULL;
或者应该有其他方法使用malloc和free?谢谢。
都可以。唯一的区别是,如果第二次尝试释放myPtr
,前一种方法会崩溃。
根据您使用的语言,malloc
行可以稍微整理一下。
使用sizeof(*myPtr)
在以后重构时更不容易出现bug。如果使用C语言,也不需要强制转换
double* myPtr = malloc(sizeof(*myPtr)*5);
正如WhozCraig所指出的,如果你正在使用c++,有更简单的方法来分配数组
std::vector<double> ar(5);
为您提供了一个包含5个double
的数组,它将在需要时增加其存储空间,并在超出作用域时自动释放其内存。
不需要在语句
中设置指针为NULLmyPtr = NULL;
一方面,这可以防止程序在第二次尝试释放指针时出现执行错误。另一方面,它可能隐藏了第二次尝试释放指针的错误代码。
因此,是否需要将指针设置为NULL取决于程序设计。
如果你说的是c++,那么最好不要使用C函数malloc和free。考虑使用智能指针,例如std::shared_ptr。
将指针设置回"NULL"只有在您需要再次重用它并对其进行检查时才有用,例如"if(myPtr){[…]}"。如果你不打算重用这个特定的指针,你可以把它留给它的值。
使用free
:
free()
只将内存块标记为空闲-没有强制执行此释放操作。对于新手和有经验的程序员来说,访问先前释放的内存块是导致许多内存错误的原因。一个好的做法是总是使刚刚释放的指针无效。
如果是C,只需去掉强制类型:
double* myPtr = malloc(sizeof(double)*5);
.....
free(myPtr);
myPtr = NULL;
你可以自由地使用你的指针做任何事情。你不一定要把它设为NULL,但如果你不想免费获得SEGFAULT,这是很好的。
让我们看看例子。
double * ptr = malloc(sizeof(double) * 42 );
ptr[0] = 1.2; // OK
free (ptr); // OK
ptr = malloc(sizeof(double) * 13); // It's OK. You don't need to set pointer to NULL
让我们再看一些例子。
void assign(ptr)
{
if( ptr != NULL) ptr[0] = 1.2;
}
double * ptr = NULL;
assign(ptr); // All OK, method will not pass check
double * ptr = malloc(sizeof(double) * 42);
assign(ptr); // OK, method will pass check and assign
free(ptr);
// ptr = NULL; // If we don't do this ....
.... a lot of code and 666 lines below ...
assign(ptr); // BAH! Segfault! And if You assign ptr=NULL, it would not a segfault
你写的是正确的(然而在C中你不应该转换malloc
的返回值,但在c++中你必须做转换)。在调用free
之后,您不必将myPtr
设置为NULL。在内存被释放后,不要取消对内存的引用。
如果可以避免,最好避免使用malloc/free
。如果
你分配的数组或结构是"小的"(你可以用手指计算大小),你知道在编译时的大小
数组在程序的局部作用域中被使用和丢弃
如果这些都是真的,不要使用malloc/free
,而只使用从堆栈而不是堆中分配的本地自动变量。
例如,
更简单,更容易维护 {
double myPtr[5];
...
}
比这 {
double* myPtr = (double*)malloc(sizeof(double)*5);
...
free(myPtr);
}
在可能的情况下使用堆栈变量是一个很好的实践,因为堆栈永远不会像堆那样"碎片化"。但是,当然,堆栈可能溢出,所以不要在堆栈上放任何"大"的东西。知道什么是"大"并不是一门精确的科学;你应该事先知道你的堆栈大小。