10

構造を定義すると...

struct LinkNode
{
  int node_val;
  struct LinkNode *next_node;
};

そして、それへのポインタを作成します...

struct LinkNode *mynode = malloc(sizeof(struct LinkNode));

...そして最後に free() それ...

free(mynode);

...構造体の「next_node」メンバーには引き続きアクセスできます。

mynode->next_node

私の質問は次のとおりです。基礎となるメカニズムのどの部分が、このメモリ ブロックが構造体 LinkNode を表すことになっているという事実を追跡しているのでしょうか? 私は C の初心者で、LinkNode へのポインターで free() を使用した後、その構造体のメンバーにアクセスできなくなると予想していました。ある種の「利用できなくなりました」という警告が表示されることを期待していました。

基礎となるプロセスがどのように機能するかについてもっと知りたいです。

4

6 に答える 6

9

struct LinkedNodeコンパイルされたプログラムには、という名前のフィールドまたはそのようなものに関する知識がなくなりますnext_node。コンパイルされたプログラムから名前は完全に削除されます。コンパイルされたプログラムは、メモリアドレス、オフセット、インデックスなどの役割を果たすことができる数値の観点から動作します。

あなたの例でmynode->next_nodeは、プログラムのソースコードを読み込むと、予約済みのメモリ位置 (ソースコードでは変数と呼ばれる) から 4 バイトの数値を読み取るだけのマシンコードにコンパイルされ、それにmynode4 が追加されます (これはnext_nodeフィールドのオフセット)、結果のアドレス ( ) で 4 バイトの値を読み取りますmynode->next_node。ご覧のとおり、このコードは、整数値 (アドレス、サイズ、およびオフセット) に関して動作します。LinkedNodeやなどの名前は気にしませんnext_node。メモリが割り当てられているか解放されているかは気にしません。これらのアクセスのいずれかが合法であるかどうかは気にしません。

(上記の例で繰り返し使用する定数 4 は、32 ビット プラットフォームに固有のものです。64 ビット プラットフォームでは、ほとんどの (またはすべての) インスタンスで 8 に置き換えられます。)

解放されたメモリを読み取ろうとすると、これらのアクセスによってプログラムがクラッシュする可能性があります。または、そうではないかもしれません。それは純粋な運の問題です。言語に関する限り、動作は未定義です。

于 2013-05-09T17:51:11.690 に答える
5

ありませんし、できません。これは、未定義の動作の典型的なケースです。

未定義の動作があると、何でも起こり得ます。機能しているように見えても、1 年後にランダムにクラッシュするだけです。

于 2013-05-09T17:28:40.597 に答える
5

解放されたメモリはまだ他の何かによって上書きされていないため、これはまったくの運で機能します。メモリを解放したら、それを再度使用しないようにするのはあなたの責任です。

于 2013-05-09T17:30:14.523 に答える
2

基礎となるメモリのどの部分もそれを追跡しません。それは、プログラミング言語がメモリのチャンクに与えるセマンティクスにすぎません。たとえば、まったく別のものにキャストしても、同じメモリ領域にアクセスできます。ただし、ここでの問題は、これがエラーにつながる可能性が高いということです。特にタイプセーフはなくなります。あなたの場合、呼び出したからといっfreeて、基になるメモリがまったく変化するわけではありません。お使いのオペレーティング システムには、この領域を再び空きとしてマークするフラグがあります。

このように考えてみてください: -free関数は「最小限の」メモリ管理システムのようなものです。呼び出しにフラグの設定以上のものが必要な場合、不必要なオーバーヘッドが発生します。また、メンバーにアクセスするとき (つまり、オペレーティング システム) は、このメモリ領域のフラグが「空き」または「使用中」に設定されているかどうかを確認できます。しかし、それはまたオーバーヘッドです。

もちろん、そのようなことをしても意味がないというわけではありません。これは多くのセキュリティ ホールを回避し、たとえば .Net や Java で行われます。しかし、これらのランタイムは C よりもはるかに古く、最近でははるかに多くのリソースがあります。

于 2013-05-09T17:28:56.470 に答える
1

mynode->next_node に NULL を割り当てる必要があります。

mynode->next_node = NULL;

メモリを解放した後、割り当てられたメモリをもう使用していないことが示されます。

NULL 値を割り当てないと、以前に解放されたメモリの場所を指しているままになります。

于 2013-05-10T00:44:23.443 に答える