释放一个字符指针

时间:2010-01-31 20:31:22

标签: c memory pointers malloc realloc

我有一个在程序执行期间多次调用的函数。在所述函数中,我有一个动态字符指针,我调整了很多次。

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

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

 //should free be called here?
 return;
}

我还应该注意,我已经尝试释放指针,但是,当我这样做时, gdb 会给我警告。

7 个答案:

答案 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但保持原始指针不变。在上面一行中,这意味着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);
    

    您只需要在一个位置将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]