我对 C 中的内存管理(以及 Debian GNU/Linux 下的 GCC 4.3.3)有疑问。
根据 K&R 的 C 编程语言书(第 7.8.5 章),当我释放一个指针然后取消引用它时,是一个错误。但是我有一些疑问,因为我注意到有时,就像我在下面粘贴的源代码中一样,编译器(?)似乎按照明确定义的原则工作。
我有一个像这样的简单程序,它显示了如何返回动态分配的数组:
#include <stdio.h>
#include <stdlib.h>
int * ret_array(int n)
{
int * arr = (int *) malloc(10 * sizeof(int));
int i;
for (i = 0; i < n; i++)
{
arr[i] = i*2;
}
printf("Address pointer in ret_array: %p\n", (void *) arr);
return arr;
}
int * ret_oth_array(int n)
{
int * arr = (int *) malloc(10 * sizeof(int));
int i;
for (i = 0; i < n; i++)
{
arr[i] = i+n;
}
printf("Address pointer in ret_oth_array: %p\n", (void *) arr);
return arr;
}
int main(void)
{
int *p = NULL;
int *x = NULL;
p = ret_array(5);
x = ret_oth_array(6);
printf("Address contained in p: %p\nValue of *p: %d\n", (void *) p, *p);
free(x);
free(p);
printf("Memory freed.\n");
printf("*(p+4) = %d\n", *(p+4));
printf("*x = %d\n", *x);
return 0;
}
如果我尝试用一些参数编译它:-ansi -Wall -pedantic-errors
,它不会引发错误或警告。不仅; 它也运行良好。
Address pointer in ret_array: 0x8269008
Address pointer in ret_oth_array: 0x8269038
Address contained in p: 0x8269008
Value of *p: 0
Memory freed.
*p+4 = 8
*x = 0
*(p+4) 是 8 而 *x 是 0。为什么会这样?如果 *(p+4) 是 8,那么 *x 不应该是 6,因为 x 数组的第一个元素是 6?
如果我尝试将调用的顺序更改为免费,则会发生另一件奇怪的事情。例如:
int main(int argc, char * argv[])
{
/* ... code ... */
free(p);
free(x);
printf("Memory freed.\n");
printf("*(p+4) = %d\n", *(p+4));
printf("*x = %d\n", *x);
return 0;
}
事实上,在这种情况下,输出(在我的机器上)将是:
*p+4 = 8
*x = 142106624
为什么x指针真的被“释放”了,而 p 指针被释放(我希望)“不同”?好的,我知道在释放内存后我应该让指针指向 NULL,但我只是好奇:P