1

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

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

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

 //should free be called here?
 return;
}

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

4

7 回答 7

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)有点奇怪,我觉得。

于 2010-01-31T20:36:02.663 回答
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()and的返回值是值得怀疑的。realloc()考虑:

// functionally identical in C
char *a = malloc(10);
char *b = (char *)malloc(10);

在 C++ 中,必须进行强制转换,因为在 C++void *中不能隐式转换为另一种指针类型。(我认为这是一个语言错误,但这不是我判断的地方。)如果您的代码是 C++,那么您应该使用newanddelete无论如何。如果您的代码是 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);
    

    您只需要更改float1double个位置。此外,始终使用sizeof *obj而不是sizeof(type)从不使用强制转换意味着以后的调用realloc()可以在没有任何更改的情况下工作,而使用强制转换和显式类型名称将需要找到您调用realloc的任何位置并更改强制转换和sizeofs。另外,如果您忘记了,请执行以下操作:

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

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

于 2010-01-31T21:39:52.447 回答
0

从手册页:

如果 size 为 0,则 malloc() 返回 NULL 或稍后可以成功传递给 free() 的唯一指针值。

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

于 2010-01-31T20:37:06.913 回答
0

是的,您需要调用一次 free() 来释放内存块。您不需要为您正在执行的后续 reallocs() 调用 free,即使它们返回不同的地址/指针。内存管理器知道不再需要旧块并将 free() 它。

于 2010-01-31T20:42:04.650 回答
0

你应该可以free(variable)在最后打电话。如果realloc必须移动数据以调整其大小,它会在free内部调用,您无需担心。

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

于 2010-01-31T20:42:26.120 回答
0

看看我对一些与内存管理有关的问题给出的一些答案:

以上所有内容都指出了显而易见的事情,对于每个 malloc 都有一个空闲的,如果没有内存泄漏,那么free当您完成指针变量mallocd 时,您必须获得内存。

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

于 2010-01-31T20:52:54.127 回答
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]
于 2013-03-27T17:43:47.353 回答