2

以下はコードです:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int *p;
    p=(int *)malloc(sizeof(int));
    *p=5;
    printf("Before freeing=%p\n",p);
    printf("Value of p=%d\n",*p);
    //making it dangling pointer
    free(p);
    printf("After freeing =%p\n",p);
    printf("Value of p=%d\n",*p);
    return 0;
}

以下は出力です。

Before freeing=0x1485010
Value of p=5
After freeing =0x1485010
Value of p=0

ポインターを解放した後、逆参照すると、出力 "0" (ゼロ) が得られます。

以下は、「0」を与える別のコードです

include <stdio.h>
#include <stdlib.h>
int main()
{
int *p;
p=(int *)malloc(sizeof(int));

printf("Before freeing=%p\n",(void *)p);
printf("Value of p=%d\n",*p);
return 0;
}

これでは、メモリを解放せず、割り当てただけですが、それでも「0」が返されます。初期化されていないすべてのポインターのデフォルト値が「0」のようですか??

なぜそうなのですか?

4

4 に答える 4

5

これに依存しないでください。これは未定義の動作です。free()ポインターをゼロに設定する必要はありません。これは、現在の実装が行っていることです。コンパイラ、プラットフォームなどに関係なく、100%確実にしたい場合は、ポインタをNULL解放した後にポインタを設定してください。

于 2013-10-22T16:20:50.023 に答える
3

未定義の動作をカバーする C99 ドラフト標準を見ると、これは単に未定義の動作です。Annex J.2

次の状況では、動作は未定義です。

次の箇条書きを含めました。

free 関数または realloc 関数の呼び出しによって解放された領域を参照するポインターの値が使用されます (7.20.3)。

通常は解放後にポインターを設定することをお勧めします。このトピックについては、ここで適切な議論NULLを見つけることができます。

于 2013-10-22T16:20:54.253 に答える
1

無効なポインターを逆参照すると、仕様ごとに未定義の結果が発生します。失敗する保証はありません。

于 2013-10-22T16:22:22.150 に答える
1

「問題ではありません。UB です」という答えは一般的には十分ですが、値が変化する理由に興味があるかもしれません。好奇心は(IMHO)何かが起こる理由を知るための正当な理由です。

「次の空きブロック」のアドレスまたは解放されたメモリ領域に何かを格納することを決定するメモリ管理に依存します。

したがって、あなたが観察しているのは、おそらくメモリ管理のアクションです。

たとえば、メモリ管理は、2 つのリンクされたリストと上位ポインタを管理する方法で実装される場合があります。1 つのリンク リストには、割り当てられたメモリ チャンクが含まれており、「実際に使用可能な」メモリの 8 バイトまたは 16 バイト前を指しています。もう 1 つのリンク リストは、次のメモリ チャンクへのポインタを含む最初の空きチャンクを指しています。上位ポインタより上のメモリは空きと見なされます。

最初のメモリ ブロックを解放すると、フリー リスト ポインターはそれを指し、最初のポインター サイズのデータ​​はゼロになります。つまり、解放されたブロックは他にありません。そして、メモリがゼロになっている理由があります。

このようなものが存在し、それらがどのように機能するかを知るのは良いことですが、その知識を製品プログラムで利用したいという誘惑は控えてください。いつかあなたの足元に落ちるかもしれません...

于 2013-10-22T16:23:18.640 に答える