如何正确使用malloc和自由内存



我想知道使用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的数组,它将在需要时增加其存储空间,并在超出作用域时自动释放其内存。

不需要在语句

中设置指针为NULL
myPtr = 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);
 }

在可能的情况下使用堆栈变量是一个很好的实践,因为堆栈永远不会像堆那样"碎片化"。但是,当然,堆栈可能溢出,所以不要在堆栈上放任何"大"的东西。知道什么是"大"并不是一门精确的科学;你应该事先知道你的堆栈大小。

相关内容

  • 没有找到相关文章

最新更新