我有一個關於(在Debian GNU/Linux和GCC 4.3.3)在C內存管理的問題。爲什麼我在釋放指針後解除引用時會得到不同的結果?
根據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
嘗試多次運行,然後比較結果 – Vaibhav 2009-07-03 10:12:15
我已經運行了至少10次,並且總是得到相同的結果 – Markon 2009-07-03 10:49:22
在同一臺機器上的單線程程序中,這些事情往往表現爲可重複的 - 這就是爲什麼他們會導致「在我的機器上工作」 - 錯誤的種類。但是,在它之前/之後添加一些代碼,添加另一個線程,使用不同的編譯器設置,您將得到不同的結果 – Niki 2009-07-03 12:59:11