C言語でfreeとmallocはどのように機能しますか?質問する

C言語でfreeとmallocはどのように機能しますか?質問する

たとえば、ポインターを「途中から」解放しようとすると何が起こるかを理解しようとしています。次のコードを見てください。

char *ptr = (char*)malloc(10*sizeof(char));

for (char i=0 ; i<10 ; ++i)
{
    ptr[i] = i+10;
}
++ptr;
++ptr;
++ptr;
++ptr;
free(ptr);

未処理の例外エラーメッセージが表示されてクラッシュします。free がなぜ、どのように動作するかを理解して、使い方だけでなく、奇妙なエラーや例外を理解し、コードをより適切にデバッグできるようにしたいです。

どうもありがとう

ベストアンサー1

ブロックを malloc すると、実際には要求したよりも少し多くのメモリが割り当てられます。この余分なメモリは、割り当てられたブロックのサイズ、ブロックのチェーン内の次の空き/使用済みブロックへのリンク、および場合によっては、割り当てられたブロックの末尾を超えて書き込んだかどうかをシステムが検出するのに役立つ「ガード データ」などの情報を格納するために使用されます。また、ほとんどのアロケータは、合計サイズやメモリの割り当て部分の開始をバイトの倍数に切り上げます (たとえば、64 ビット システムでは、データが 64 ビット (8 バイト) の倍数に揃えられることがあります。これは、揃えられていないアドレスからデータにアクセスすると、プロセッサ/バスにとってより困難で非効率的になる可能性があるためです)。そのため、最終的に「パディング」(未使用のバイト) が残ることもあります。

ポインタを解放すると、そのアドレスを使用して、割り当てられたブロックの先頭(通常)に追加された特別な情報を検索します。別のアドレスを渡すと、ゴミを含むメモリにアクセスするため、その動作は未定義になります(ただし、ほとんどの場合、クラッシュが発生します)。

後で、ブロックを free() してもポインタを「忘れない」と、将来そのポインタを介して誤ってデータにアクセスしようとする可能性があり、動作は未定義です。次のいずれかの状況が発生する可能性があります。

  • メモリは空きブロックのリストに入れられる可能性があるため、アクセスすると、そこに残したデータがまだ含まれており、コードは正常に実行されます。
  • メモリ アロケータがメモリ (の一部) をプログラムの別の部分に渡した可能性があり、それによって古いデータ (の一部) が上書きされた可能性があります。そのため、それを読み取ると、コードが予期しない動作をしたりクラッシュしたりする可能性のあるゴミが取得されます。または、他のデータを上書きして、将来のある時点でプログラムの他の部分が異常な動作をする原因になります。
  • メモリはオペレーティング システムに返されている可能性があります (使用しなくなったメモリの「ページ」はアドレス空間から削除できるため、そのアドレスで使用できるメモリはなくなります。つまり、アプリケーションのメモリに未使用の「穴」ができます)。アプリケーションがデータにアクセスしようとすると、ハード メモリ障害が発生し、プロセスが強制終了されます。

このため、ポインタが指しているメモリを解放した後はポインタを使用しないようにすることが重要です。このためのベストプラクティスは、メモリを解放した後でポインタをNULLに設定することです。これは、NULLを簡単にテストできるためです。また、NULLポインタを介してメモリにアクセスしようとすると、悪い結果が発生しますが、一貫性のある動作が修正され、デバッグがはるかに簡単になります。

おすすめ記事