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

elb*_*ker 1 c memory

假设我有以下代码:

int *ptr = (int*) malloc(0), *ptr2;
ptr2 = (int*) malloc(4 * sizeof(int));
*(ptr2 + 1) = 3;
ptr = ptr2;
free(ptr)
Run Code Online (Sandbox Code Playgroud)

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

Cra*_*tey 6

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

\n

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

\n

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

\n

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

\n
int *ptr = (int *) malloc(0), *ptr2;\n\nptr2 = (int *) malloc(4 * sizeof(int));\n*(ptr2 + 1) = 3;\n\n// to prevent a leak of the first malloc ...\nint *ptr3 = ptr;\n\n// without ptr3, this would "leak" the original value of ptr\nptr = ptr2;\nfree(ptr)\n\n// free the first block ...\nfree(ptr3);\n
Run Code Online (Sandbox Code Playgroud)\n
\n

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

\n

因此,在代码中执行以下操作(例如):

\n
ptr2 = malloc(4 * sizeof(int));\n
Run Code Online (Sandbox Code Playgroud)\n

仍然存在一些额外的代码复制。sizeof(int)如果我们改变了 的类型,就必须改变ptr2

\n

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

\n
ptr2 = malloc(sizeof(*ptr2) * 4);\n
Run Code Online (Sandbox Code Playgroud)\n
\n

更新:

\n
\n

malloc(0)您还可以添加有关实现定义行为的注释。\xe2\x80\x93\nchqrlie

\n
\n

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

\n
    \n
  1. 返回NULL。IMO,最好的选择
  2. \n
  3. 将内部分配视为malloc(1)
  4. \n
  5. 返回特殊的“零长度”分配。
  6. \n
\n

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

\n

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

\n

不过,realloc接受NULL指针就好了。

\n

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

\n
#include <stdio.h>\n#include <stdlib.h>\n\nint\nmain(int argc,char **argv)\n{\n\n    if (argc < 2)\n        exit(3);\n\n// NOTE: novices do this ...\n#if 0\n    int *ptr = malloc(0);\n// NOTE: experienced programmers do this ...\n#else\n    int *ptr = NULL;\n#endif\n\n    // number of elements in the array\n    size_t count = 0;\n\n    // open the input file\n    FILE *input = fopen(argv[1],"r");\n    if (input == NULL) {\n        perror(argv[1]);\n        exit(4);\n    }\n\n    while (1) {\n        // increase array size\n        ptr = realloc(ptr,sizeof(*ptr) * (count + 1));\n\n        // out of memory ...\n        if (ptr == NULL) {\n            perror("realloc");\n            exit(5);\n        }\n\n        // decode one number from file\n        if (fscanf(input,"%d",&ptr[count]) != 1)\n            break;\n\n        // advance the count\n        ++count;\n    }\n\n    // close the input stream\n    fclose(input);\n\n    // trim array to actual size used\n    ptr = realloc(ptr,sizeof(*ptr) * count);\n\n    // print the array\n    for (size_t idx = 0;  idx < count;  ++idx)\n        printf("%zu: %d\\n",idx,ptr[idx]);\n\n    // free the array\n    free(ptr);\n\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

注意:在少数特殊情况下,这样做malloc(0) 确实有意义。通常,指针必须传递给一些代码来区分NULL分配malloc(0)与常规分配。但是,它们是高级用法,我不会向初学者推荐它们。

\n