我的程序中有几个方法,其中我有一个字符*str,我malloc,然后需要在方法结束时返回str。我不知道我需要在这些方法中放置 free() 语句的位置。如果我在返回 str 之前释放(),str 是空的,如果我在返回语句之后这样做,我想它不会在正确的时间被释放吗?例如,如果我在程序被释放之前退出程序,这将产生内存泄漏。正确的方法是什么?
通过阅读您的问题,我认为您对malloc和free的工作原理有错误的理解。
Malloc 将在您的进程堆上分配空间。此堆是全局的,这意味着您可以从代码中的任何位置(而不仅仅是在函数中)访问它。因此,您还可以在代码中的任何位置释放它。如果您返回指向已分配空间的指针,则在同一函数中释放它是没有意义的(否则您有一个悬空指针,即引用已释放空间的指针)。因此,将指针从函数以外的其他任何地方释放是完全可以的(也是必要的)。
此外,正如您所说,您的进程"退出后"不会发生内存泄漏。内存泄漏发生在进程内部;这意味着进程的某些堆被分配,但不再使用(并且没有引用它,因此无法再释放它)。当你的程序占用堆上的大量空间时,这可能会导致内存不足问题(而且这对性能安利不利,所以你永远不希望这种情况发生)。但是,当您的进程退出时,操作系统无论如何都会释放它的所有内存(包括堆)。因此,不再有内存泄漏(除非您正在处理多线程,但这是一个不同的主题)。
能让我的代码遵循以下模式,我通常会很高兴:
char * foo_allocate() {
char * s = malloc(10);
snprintf(s, 10, "hello");
return s;
}
void foo_release(char *s) {
free(s);
}
不再需要缓冲区内容时释放缓冲区,而不是在之前释放缓冲区。
你的模式是这样的:
char *SomeFunction()
{
...
return malloc(somelength) ;
}
...
char *mychar = SomeFunction() ;
... // deal with the mychar buffer
free(mychar);
...
分配的内存的位置并不重要,只要您不要忘记释放它。在我看来,放置free()的最佳位置是在从函数返回之前,在称为cleanup的标签中。这样,您就不会有内存泄漏,因为如果您确保每个函数都没有内存泄漏,那么您的整个程序就不会有内存泄漏。
你的函数应该看起来像这样:
int func(void)
{
/* Code that has allocations in it */
cleanup:
/* Here you should free all of your allocations */
return 0;
}
如果您使用的是Linux,则可以使用valgrind以确保没有任何内存泄漏。
这个问题有很多替代方案,这里有一些解决方案:
1-使用一个函数进行分配,另一个函数进行释放,正如比尔·林奇(Bill Lynch)在他的答案中发布的那样。当您使用具有良好实践的结构(创建构造函数和析构函数)时,通常会使用此方法。
2-使用该函数的人负责释放它返回的字符串。
3-您可以将返回值作为参数传递,下面是一个示例:
void foo(char* s) {
snprintf(s, 10, "hello");
}
请注意,当您想要返回一个退出代码说一切都已写入时,经常使用最后一个解决方案(您会发现许多使用它的函数)。
int foo(char* s) {
snprintf(s, 10, "hello");
return 1; // everything went well
}
在使用分配的内存的最高级别函数中,调用 free()
以释放内存。
释放后,将值设置为 NULL
可确保后续使用s
不会使用释放的内存。 如果随后未访问该变量,则编译器可能会优化不需要的s = NULL;
。
char *Allocator() {
...
char *s = malloc(...);
...
return s;
}
void foo() {
...
char *s = Allocator;
// ... use s
free(s);
s = NULL;
...
}