首页 > 解决方案 > free() 是否适用于重新分配的指针?

问题描述

假设我有以下代码:

int *ptr = (int*) malloc(0), *ptr2;
ptr2 = (int*) malloc(4 * sizeof(int));
*(ptr2 + 1) = 3;
ptr = ptr2;
free(ptr)

调用 free(ptr) 是否适用于新的内存块 ptr 指向或在空指针上?

标签: cmemory

解决方案


是的,在您的示例ptr中设置为ptr2来自malloc.

所以,free(ptr); 有效的(例如,就像我们做的那样free(ptr2);)。

但是,现在,我们已经丢失了 的原始值,ptr所以第一个块现在 malloc是内存泄漏。也就是说,没有变量具有原始值,因此它永远不能被释放。

要解决这个问题,但保留您的原始代码,我们可以这样做:

int *ptr = (int *) malloc(0), *ptr2;

ptr2 = (int *) malloc(4 * sizeof(int));
*(ptr2 + 1) = 3;

// to prevent a leak of the first malloc ...
int *ptr3 = ptr;

// without ptr3, this would "leak" the original value of ptr
ptr = ptr2;
free(ptr)

// free the first block ...
free(ptr3);

旁注: malloc returnsvoid *适用于任何指针类型,因此无需转换返回值。请参阅:我是否强制转换 malloc 的结果?

所以,在代码中做(例如):

ptr2 = malloc(4 * sizeof(int));

仍然有一些额外的代码复制。如果sizeof(int)我们改变了ptr2.

因此,为了“面向未来”的代码,许多人更喜欢:

ptr2 = malloc(sizeof(*ptr2) * 4);

更新:

您还可以添加关于malloc(0)具有实现定义的行为的注释。– chqrlie

是的,malloc(0)具有实现定义的行为。一些可能性:

  1. 退货NULL。海事组织,最佳选择
  2. 将内部分配视为malloc(1)
  3. 返回一个特殊的“零长度”分配。

由于这些原因,我会避免使用。malloc(0)它是“脆弱的”并且具有边际效用。

我 [大部分] 看到新手程序员使用它,他们计划realloc在循环中使用并相信他们不能调用realloc指针NULL

但是,realloc会接受一个NULL指针就好了。

例如,如果我们要将一个填充了整数的文件读入一个数组,而我们不知道文件中有多少个数字,我们可能会这样做:

#include <stdio.h>
#include <stdlib.h>

int
main(int argc,char **argv)
{

    if (argc < 2)
        exit(3);

// NOTE: novices do this ...
#if 0
    int *ptr = malloc(0);
// NOTE: experienced programmers do this ...
#else
    int *ptr = NULL;
#endif

    // number of elements in the array
    size_t count = 0;

    // open the input file
    FILE *input = fopen(argv[1],"r");
    if (input == NULL) {
        perror(argv[1]);
        exit(4);
    }

    while (1) {
        // increase array size
        ptr = realloc(ptr,sizeof(*ptr) * (count + 1));

        // out of memory ...
        if (ptr == NULL) {
            perror("realloc");
            exit(5);
        }

        // decode one number from file
        if (fscanf(input,"%d",&ptr[count]) != 1)
            break;

        // advance the count
        ++count;
    }

    // close the input stream
    fclose(input);

    // trim array to actual size used
    ptr = realloc(ptr,sizeof(*ptr) * count);

    // print the array
    for (size_t idx = 0;  idx < count;  ++idx)
        printf("%zu: %d\n",idx,ptr[idx]);

    // free the array
    free(ptr);

    return 0;
}

注意:在某些特殊情况下,这样做malloc(0) 确实有意义。通常,必须将指针传递给一些代码,这些代码将区分NULLmalloc(0)常规分配。但是,它们是一种高级用法,我不建议初学者使用它们。


推荐阅读