free(a) を呼び出すと、正確には何が起こっているのでしょうか?
これは実装固有です。例として、Linux と glibc では、次のいずれかが発生する可能性があります。
メモリが 128k 以上のブロックに割り当てられた場合、 は新しいメモリ領域を割り当てます (具体的には、のglibc
コピー オン ライト)。解放されると、メモリ領域は単純に割り当て解除 ( 'd) されて消えます。さらにアクセスするとクラッシュします。mmap
/dev/zero
munmap
割り当てられたメモリが小さかった場合は、ヒープに移動します。ヒープは、固定アドレスから始まる単一のメモリ領域であり、プロセスが縮小または拡大できるサイズです ( を使用sbrk
)。
メモリ アロケータは、この領域のどの部分が割り当てられているかを追跡します。初めて何かが割り当てられると、ヒープのサイズが増加し、この新しい領域の最後にメモリが追加されます。
このようなメモリ ブロックを解放すると、ヒープの最後でヒープ サイズが縮小され、メモリが無効になり、その後のアクセスがクラッシュする可能性があります。ただし、アロケータは数バイトだけヒープ サイズを増減することはありません。したがって、その時点では、割り当てのサイズと解放されたブロックの数によって異なります。アクセスできる場合とそうでない場合があります。
10 ブロックのメモリを割り当て、最初の 9 ブロックを解放すると、ヒープに未使用の領域ができてしまいます。終了アドレスを設定することによってのみヒープ サイズを変更できるため、実際には何もできません。メモリは引き続き有効であり、アクセスは引き続き機能します。おそらく元のデータもそこにあり、何も起こらなかったかのように続行できます。
ただし、新しいメモリが割り当てられると、malloc
はそれをこの未使用領域に配置しようとするため、他のデータが元のメモリを上書きします。解放された配列に int を設定すると、プログラムのまったく関係のない部分でポインターが上書きされる可能性があり、陽気さとデバッグが続きます。
tl;dr: 解放されたメモリにアクセスしないでください!