我有一个在程序执行期间多次调用的函数。在所述函数中,我有一个动态字符指针,我调整了很多次。
我的问题是:我需要在函数结束前释放这个指针吗?
void functionName()
{
char *variable = (char *) malloc(0);
//variable is resized with realloc x number of times
//should free be called here?
return;
}
我还应该注意,我已经尝试释放指针,但是,当我这样做时, gdb 会给我警告。
答案 0 :(得分:3)
是的,你必须释放它,否则你会泄漏内存。您的代码应如下所示:
void function(void)
{
char *variable = (char *)malloc(0);
variable = realloc(variable, 10);
// do something with new memory
variable = realloc(variable, 20);
// do something with more new memory
free(variable); // clean up
}
我认为,调用malloc(0)
有点奇怪。
答案 1 :(得分:3)
要点几点:
我无法看到你在代码中如何使用realloc()
,但如果你这样使用它,那就错了:
variable = realloc(variable, amount);
当它无法分配更多内存时,realloc()
会返回NULL
但保持原始指针不变。在上面一行中,这意味着variable
是NULL
并且我们已经失去了对它所指向的内存的访问权限,但是该内存尚未被释放。正确的习语就是:
void *tmp = realloc(variable, amount);
if(tmp)
{
// success! variable invalid, tmp has new allocated data
variable = tmp;
}
else
{
// failure! variable valid, but same size as before, handle error
}
你应该使用第二个的原因是因为realloc()
失败很糟糕,但在许多情况下都是可以恢复的,不像malloc()
,其中失败通常意味着“停止一切并死亡”。
这是一个更具争议性的问题,但您是否应该像您一样转换malloc()
和realloc()
的返回值是值得怀疑的。考虑:
// functionally identical in C
char *a = malloc(10);
char *b = (char *)malloc(10);
在C ++中,必须进行强制转换,因为在C ++中void *
不能隐式转换为另一种指针类型。 (我认为这是一个语言错误,但这不是我判断的地方。)如果您的代码是C ++,那么您应该使用new
和delete
。如果您的代码是C但需要使用C ++编译器进行编译(出于某种无聊的原因),您别无选择,只能进行强制转换。如果您不需要使用C ++编译器编译C代码(类似于必须在Python解释器中运行Ruby代码),请继续以下几点,这就是为什么我认为您不应该强制转换。
在C89中,如果在未声明的情况下使用某个函数,它将被隐式声明为返回int
。例如,如果我们忘记了#include <stdlib.h>
并且我们调用了malloc()
,那么没有强制转换的版本会导致编译器错误(不允许从int
到char *
的隐式强制转换),而带有演员的版本会(错误地)告诉编译器“我知道这听起来很疯狂,但无论如何都要施展它。”大多数编译器会给你一个内置函数(如malloc()
)的隐式(或不可复制)声明的警告,但是强制转换确实会让它更难找到。
说你有一些数据:
float *array = (float *)malloc(10 * sizeof(float));
稍后,您会发现数据需要更高的精度,并且必须将其设为double
数组。在上面的行中,您需要更改不超过3个不同的位置:
double *array = (double *)malloc(10 * sizeof(double));
另一方面,如果你写了:
float *array = malloc(10 * sizeof *array);
您只需要在一个位置将float
更改为double
。此外,始终使用sizeof *obj
代替sizeof(type)
并且从不使用强制转换意味着稍后调用realloc()
可以使用而无需任何更改,同时使用强制转换和显式类型名称需要找到您调用realloc
的任何地方并更改演员表和sizeof
。此外,如果你忘了,并执行此操作:
double *array = (float *)malloc(10 * sizeof(float));
在大多数平台上,array
现在只是一个包含5个元素的数组,假设对齐没有关闭,编译器不会抱怨你正在为float *
分配double *
{1}}。有些人认为编译器发出的警告是有用的,因为它指出了可能不正确的行。但是,如果我们避免sizeof(type)
并避免强制转换,我们可以看到行不会不正确,因此让编译器引起对它们的注意是浪费时间我们可以用来编程
答案 2 :(得分:0)
从手册页:
如果size为0,则malloc()返回NULL或一个以后可以成功传递给free()的唯一指针值。
所以,我相信答案是“是”:)。
答案 3 :(得分:0)
是的,您需要调用free()一次以释放内存块。你不需要为你正在做的后续reallocs()调用free,即使那些返回不同的地址/指针。内存管理器知道不再需要旧块,并且将释放()它。
答案 4 :(得分:0)
您应该可以在结尾处拨打free(variable)
。如果realloc
必须移动数据以调整其大小,它会在内部调用free
,您无需担心这一点。
此外,在初始化variable
的位置,您只需将其设置为NULL
,而不是调用malloc
; realloc
第一次就像malloc
一样工作。
答案 5 :(得分:0)
看看我对内存管理方面的几个问题给出的一些答案:
以上所有都指出了显而易见的事情,对于每个malloc都有一个免费的,如果不是你有内存泄漏,所以你必须free
内存时你完成了malloc
d。
希望这有帮助, 最好的祝福, 汤姆。
答案 6 :(得分:0)
int main(int argc, char *argv[])
{
char *p = malloc(sizeof(argv[1]));
p = argv[1];
printf("%s\n", p);
free(p);
return 0;
}
我得到了glibc错误
hello
*** glibc detected *** ./a.out: munmap_chunk(): invalid pointer: 0x00007fff66be94c6 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7f38dca1db96]
./a.out[0x4005ed]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f38dc9c076d]