free() 是否适用于重新分配的指针?

Does free() work on a reassigned pointer?

假设我有以下代码:

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

调用 free(ptr) 是否对 ptr 指向的新内存块或空指针起作用?

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

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

但是,现在,我们已经 丢失了 原始 ptr 值,所以来自 first 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 returns void *,适用于 any 指针类型,所以 no 需要转换 return 值。参见:Do I cast the result of malloc?

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

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

还有一些额外的代码复制。如果我们更改 ptr2.

的类型,则必须更改 sizeof(int)

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

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

更新:

You might also add a note about malloc(0) having implementation defined behavior. – chqrlie

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

  1. ReturnsNULL。 IMO,最好的选择
  2. 在内部将分配视为 malloc(1)
  3. Returns 特殊的“零长度”分配。

出于这些原因,我会避免使用malloc(0)。它“脆弱”且效用有限。

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

然而,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) 与常规分配。但是,它们是 高级 用法,我不建议初学者使用它们。

free(ptr) 将释放 ptr2 指向的四个“整数”。更改未分配的内存不会使其分配。

我会警告你这里有内存泄漏。 ptr 最初指向的内存仍将被分配但未被引用。