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)
具有实现定义的行为。一些可能性:
- Returns
NULL
。 IMO,最好的选择
- 在内部将分配视为
malloc(1)
- 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)
确实有意义。通常,必须将指针传递给一些代码,这些代码将区分 NULL
与 malloc(0)
与常规分配。但是,它们是 高级 用法,我不建议初学者使用它们。
free(ptr) 将释放 ptr2 指向的四个“整数”。更改未分配的内存不会使其分配。
我会警告你这里有内存泄漏。 ptr 最初指向的内存仍将被分配但未被引用。
假设我有以下代码:
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)
具有实现定义的行为。一些可能性:
- Returns
NULL
。 IMO,最好的选择 - 在内部将分配视为
malloc(1)
- 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)
确实有意义。通常,必须将指针传递给一些代码,这些代码将区分 NULL
与 malloc(0)
与常规分配。但是,它们是 高级 用法,我不建议初学者使用它们。
free(ptr) 将释放 ptr2 指向的四个“整数”。更改未分配的内存不会使其分配。
我会警告你这里有内存泄漏。 ptr 最初指向的内存仍将被分配但未被引用。