是的,在您的示例中,ptr 设置为来自malloc 的ptr2。
所以,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返回void *,适用于任何指针类型,所以没有需要强制转换返回值.见:Do I cast the result of malloc?
所以,在代码中做(例如):
ptr2 = malloc(4 * sizeof(int));
还有一些额外的代码复制。如果我们更改了 ptr2 的类型,则必须更改 sizeof(int)。
所以,为了“面向未来”的代码,很多人更喜欢:
ptr2 = malloc(sizeof(*ptr2) * 4);
更新:
您还可以添加关于 malloc(0) 具有实现定义行为的注释。 –
chqrlie
是的,malloc(0) 具有实现定义的行为。一些可能性:
- 返回
NULL。 IMO,最佳选择
- 在内部将分配视为
malloc(1)
- 返回一个特殊的“零长度”分配。
出于这些原因,我会避免使用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)确实有意义。通常,必须将指针传递给一些代码,这些代码将辨别NULL 与malloc(0) 与常规分配。但是,它们是一种高级用法,我不建议初学者使用它们。