2010-01-31 80 views
1

我有一个函数在程序执行过程中被多次调用。在这个函数中,我有一个动态的字符指针,我可以调整大小。释放字符指针

我的问题是:我需要在函数结束之前释放这个指针吗?

void functionName() 
{ 
char *variable = (char *) malloc(0); 
    //variable is resized with realloc x number of times 

//should free be called here? 
return; 
} 

我也应该注意到,我试图释放指针,不过,GDB给我警告,当我这样做。

+0

什么警告并GDB给你? – ezod 2010-01-31 20:38:57

回答

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)是有点不可思议,我想。

+0

gdb给了我: 警告:堆块在003E2468修改为003E25C8过去请求的大小为158 – 2010-01-31 20:40:07

+2

这个警告听起来像是你在某个时候溢出你的缓冲区,或者用'malloc() '/'realloc()'调用。 – 2010-01-31 20:41:28

+0

事实证明,我并没有为我正在输入的数据重新分配足够的内存。 感谢您的帮助! – 2010-01-31 20:49:01

0

从手册页:

如果大小为0,那么malloc()函数返回值为NULL,或者以后可以顺利通过释放的唯一指针值()。

所以,我相信答案是“是”:)。

0

是的,你需要调用free()一次释放内存块。您不需要为后续的reallocs()函数免费调用,即使这些函数返回不同的地址/指针。内存管理器知道旧块不再需要,并释放()它。

0

您应该可以在最后拨打free(variable)。如果realloc有史以来必须移动数据以调整它的大小,它在内部调用free,你不需要担心。

此外,在初始化variable时,您可以将其设置为NULL而不是调用malloc; realloc将首次像malloc一样工作。

0

看一看一些我已经给了一对夫妇的关系问题,内存管理问题的答案:

上述所有的点出了明显的事情,每一个的malloc有一个免费的,如果不是你有内存泄漏的,所以它是你必须free内存当你与完成你的指针变量是malloc d。

希望这会有所帮助, 最好的问候, 汤姆。

+0

顺便说一句,应该指出,有人今天有一个确切的问题,题为'C stdlib realloc问题'... – t0mm13b 2010-01-31 21:44:58

3

几个点使:

我看不出你如何在代码中使用realloc(),但如果你使用它这样的,这是错误的:

variable = realloc(variable, amount); 

当它是无法分配更多内存,realloc()返回NULL,但保持原始指针不变。在上面的行中,这意味着variableNULL,我们已经失去了它指向的内存的访问权限,但是该内存没有被释放。正确的成语是:

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++,那么无论如何您应该使用newdelete。如果你的代码是C但需要用C++编译器进行编译(出于某种原因),你别无选择,只能进行强制转换。如果您不需要使用C++编译器编译C代码(类似于必须在Python解释器中运行Ruby代码),请继续以下几点,这就是我认为您不应该投射的原因。

  1. 在C89,如果没有被声明使用的功能,它将被隐式地声明为返回一个int。如果我们忘记了#include <stdlib.h>并且我们调用malloc(),那么没有强制转换的版本会导致编译器错误(不允许隐式强制转换intchar *),而带有强制转换的版本会(错误地)告诉编译器“我知道这听起来很疯狂,但无论如何都要投它。“大多数编译器会给你一个隐含的(或不兼容的)声明,像malloc()这样的内置函数的声明,但是演员确实很难找到它。

  2. 假设你有一些数据:

    float *array = (float *)malloc(10 * sizeof(float)); 
    

    后来,你发现你需要在你的数据更加精确,并有使这个double阵列。在上面的线,你需要改变不超过3个不同的地方:

    double *array = (double *)malloc(10 * sizeof(double)); 
    

    如果,另一方面,你这样写:

    float *array = malloc(10 * sizeof *array); 
    

    你只需要改变floatdouble在1个地方。此外,始终使用sizeof *obj代替sizeof(type)从不使用强制转换意味着对realloc()以后的调用可以工作没有任何变化,而使用强制转换和显式定义名称将需要找到任何你叫realloc和改变铸件和sizeof秒。另外,如果你忘了,而做到这一点:

    double *array = (float *)malloc(10 * sizeof(float)); 
    

    在大多数平台上,array现在只有5个元素的数组,假设对准不关闭,编译器不抱怨你将float *分配给double *。有些人认为编译器发出的警告是有帮助的,因为它指出了可能不正确的行。但是,如果我们避免sizeof(type)并避免投射,我们可以看到行不会是不正确,因此让编译器引起他们的注意力正在浪费时间来编程。

+0

作为补充,大多数感觉需要投出malloc结果的人通常不会感觉到需要将参数强制转换为free()。通常是没有真正理解的普通货物崇拜的确切标志。 – Secure 2010-01-31 22:26:18

+0

@Secure:更可能是使用C++的标志,其中有一个从char *到void *的隐式转换,但不是另一种方式。就我个人而言,我认为如果在malloc中使用'sizeof(type)',那么*为了安全起见,您应该强制键入*。在你初始化一个指针变量的情况下,它根本就不安全,但是在赋值的时候是这样。但是,正如Chris所指出的,你可能不应该在malloc中使用'sizeof(type)'来开始。最好将大小放在将要分配结果的指针上,然后忽略该强制转换。 – 2010-01-31 22:38:27

+0

@secure:什么是货物崇拜? – t0mm13b 2010-01-31 22:39:01

0
int main(int argc, char *argv[]) 
{ 
     char *p = malloc(sizeof(argv[1])); 

     p = argv[1]; 
     printf("%s\n", p); 
     free(p); 
     return 0; 
} 

IAM获得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]