2014-11-21 124 views
0

我在我的程序中有几个方法,我有一个char * str,这是malloc,然后需要在方法结束时返回str。在我需要在这些方法中放入free()语句的地方我很困惑。如果我在返回str之前释放(),那么str是空的,如果我在返回语句之后执行它,它将不会在我猜的正确时间释放?如果我例如在程序释放之前退出程序,这会造成内存泄漏。什么是正确的方法来做到这一点?正确使用free()方法返回+ C

+2

接收指针的代码应该释放某处的内存。当你完成它的时候,简单地释放内存。 – 2014-11-21 20:00:50

+1

如果你的函数正在分配内存,填充一些有用的东西并返回指针,应该记录下来,指针应该被调用代码释放。 – 2014-11-21 20:02:09

+0

当你不再使用它时,你应该释放它。 – anothertest 2014-11-21 20:02:50

回答

0

从阅读你的问题,我认为你对malloc和free的作品有一个错误的理解。

Malloc将在您的进程堆上分配空间。这个堆是global,这意味着你可以从代码中的任何地方访问它(而不仅仅是在你的函数中)。因此,您也可以在代码中的任意位置免费使用。如果你返回一个指向已分配空间的指针,那么在同一个函数中释放它是没有意义的(否则你有一个悬挂指针,即指向已经释放空间的指针)。因此,从其他任何位置释放指针(除了函数外)是完美的(也是必要的)。

此外,您的流程退出后,您没有内存泄漏,如您所述。发生内存泄漏内部进程;这意味着该进程的一些堆被分配,但不再使用(并且没有引用它,所以它不能再被释放)。当你的程序在堆上占用大量空间时,这可能会导致内存不足问题(并且它对性能不利,所以你不希望发生这种情况)。 但是当你的进程退出时,它的内存(包括他堆)的全部无论如何都被操作系统解除分配。所以,没有内存泄漏了(除非你正在处理多线程,但这是一个不同的话题)。

+0

谢谢你的一个很好的解释!你是对的,我还没有完全理解它是如何工作的,但我觉得我现在理解我多一点:) – user16655 2014-11-21 20:43:43

2

我经常很高兴,如果我可以让我的代码遵循此模式:

char * foo_allocate() { 
    char * s = malloc(10); 
    snprintf(s, 10, "hello"); 
    return s; 
} 

void foo_release(char *s) { 
    free(s); 
} 
+0

谢谢!我没有想到我可以从程序中的另一个方法/地方释放它。 – user16655 2014-11-21 20:08:47

+0

'asprintf()'在这样的环境中相当不错:它自动为您分配足够的内存。没有弄乱固定缓冲区大小,你肯定会得到错误的/随着使用量的增加必然会变得不足......你可能还会提到,它*应该*被记录为调用者需要释放缓冲区。 – cmaster 2014-11-21 20:16:55

+0

@cmaster:'snprintf()'只是一个例子。也许数据来自套接字或来自任何其他地方...... – 2014-11-21 20:20:20

1

您必须释放缓冲区,当你不需要它的内容了,而不是之前。

你的模式是这样的:

char *SomeFunction() 
{ 
    ... 
    return malloc(somelength) ; 
} 

... 
char *mychar = SomeFunction() ; 
... // deal with the mychar buffer 

free(mychar); 
... 
0

这真的dosnt不管你在哪里释放你分配的内存,只要你不要忘了释放它。在我看来,把free()的最好的地方放在函数返回之前,就是一个名为cleanup的标签。 这样,你就不会有内存泄漏,因为如果你确信在每一个没有内存泄漏的函数中,你的整个程序都不会有内存泄漏。

你的职能应该somethinhg这样的:

int func(void) 
{ 
    /* Code that has allocations in it */ 
cleanup: 
    /* Here you should free all of your allocations */ 
    return 0; 
} 

如果你使用Linux,你可以使用valgrind,以确保你没有任何内存泄漏。

0

没有关于这个问题很多的选择,这里有一些解决方案:

1-使用函数来分配,另一个是免费为比尔·林奇在后他的回答。当你使用具有良好实践的结构(你创建了一个构造函数和一个析构函数)时,这是正常使用的。

2-使用函数的人负责释放返回的字符串。

3 - 你可以通过返回值作为参数,这里有一个例子:

void foo(char* s) { 
    snprintf(s, 10, "hello"); 
} 

请注意,最后的解决方案是经常使用,当你想要返回的退出代码说,一切都写(你会发现许多使用这个功能)。

int foo(char* s) { 
     snprintf(s, 10, "hello"); 
     return 1; // everything went well 
} 
+0

此类用户提供的缓冲区通常是灾难收据。更好地返回一个合适的'malloc()'ed缓冲区 – cmaster 2014-11-21 20:18:45

0

在使用分配内存的最高级别函数中,请调用free()来释放内存。

释放后,将值设置为NULL确保后续使用s不使用已释放的内存。如果随后没有访问该变量,那么不需要的编译器可能会优化出不需要的编译器s = NULL;

char *Allocator() { 
    ... 
    char *s = malloc(...); 
    ... 
    return s; 
} 


void foo() { 
    ... 
    char *s = Allocator; 
    // ... use s 
    free(s); 
    s = NULL; 
    ... 
}