私はC(とDebian GNU/LinuxのGCC 4.3.3)のメモリ管理について質問しました。ポインタを解放した後に逆参照すると、結果が変わるのはなぜですか?
Cのプログラミング言語の書籍K & Rによると(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ポインタがある間、
*p+4 = 8
*x = 142106624
はなぜXポインタは本当に、「解放」されません私は「異なって」解放されましたか? [OK]を、私はメモリを解放した後、私はポインタがNULLを指すようにすべきであることを知っているが、私はちょうど興味があった:P
複数回実行してから結果を比較してみてください – Vaibhav
私は少なくとも10回実行しましたが、いつも同じ結果が得られます – Markon
同じマシン上のシングルスレッドプログラムでは、これらはしばしば再現性があります。なぜ彼らが「機械上の仕掛け」につながるのか?バグの種類。しかし、その前/後にいくつかのコードを追加し、別のスレッドを追加して、別のコンパイラ設定を使用すると、別の結果が得られます – Niki