タイトルが示唆するように、私はCに不慣れで、まもなく中間期が近づいています。私は現在、過去の論文から改訂しており、繰り返し発生するテーマは二重自由問題です。同じメモリロケーションで2回free()
を呼び出すプロセスであることは理解していますが、回答方法が100%わからない質問がいくつかあります。
質問1:Cでのダブルフリーの結果は何ですか?なぜそれがそのような問題なのですか?
これにより、二重の空きが発生します。
char* ptr = malloc(sizeof(char));
*ptr = 'a';
free(ptr);
free(ptr);
これに対する私の応答は、0x0のメモリアドレスを返し、システムが不安定になる/クラッシュすることになります。また、私が正しく覚えている場合は、double freeが実際にmalloc
を2回呼び出す可能性があり、その結果、バッファオーバーフローが発生し、システムが脆弱なままになります。
この質問を簡単にまとめる最良の方法は何でしょうか?
質問2:Cでダブルフリーを導入するのが特に簡単な状況について説明してください
あなたの周りにポインターを渡すと、1つの関数で誤ってそれを解放し、気付かずに再び解放する可能性があると考えていました。
繰り返しますが、これをまとめる「最良の」方法は何ですか?
Cでのダブルフリーは、技術的にはndefined behaviorにつながります。これは、プログラムが完全に勝手に振る舞うことができ、何が起こるかについてすべての賭けがずれていることを意味します。これは確かに悪いことです!実際には、メモリブロックを2回解放すると、メモリマネージャの状態が破損します。これにより、既存のメモリブロックが破損したり、将来の割り当てが奇妙な方法で失敗したりする可能性があります(たとえば、同じメモリが2つに渡される) malloc
の異なる連続呼び出し)。
二重解放は、あらゆる種類のケースで発生する可能性があります。かなり一般的なのは、複数の異なるオブジェクトがすべて互いにポインタを持ち、free
の呼び出しによってクリーンアップを開始する場合です。これが発生した場合、注意しないと、オブジェクトをクリーンアップするときに同じポインタを複数回free
する可能性があります。他にも多くのケースがあります。
お役に立てれば!
なぜなら、free()は、各リージョンの前にタグに格納された情報を管理することにより、隣接するリージョンを統合します。これは、二重リンクリストを管理するようなものです。したがって、ptr
が指しているバッファーが、偽のタグが挿入される可能性がある攻撃文字列によって上書きされている場合は危険です。
この質問への回答は良好ですが、「重複する質問」リンクに「どうやって回避するのですか?」
投稿されたサンプルコードに1行追加されます。
char* ptr = malloc(sizeof(char));
*ptr = 'a';
free(ptr);
ptr = NULL; // add this
free(ptr);
関数free
は、NULL
ポインターでは何もしません。
公開されたC11標準に従って、すでにfree
のメモリロケーションでfree
を呼び出すと、未定義の動作が発生します。メモリが使用可能でも割り当てられない、ヒープが破損する、同じメモリの場所が別のmallocに割り当てられるなど、奇妙な状況につながる可能性があります。基本的に、未定義であり、何でもかまいません。
ANSI C11 stdはここにあります。 https://www.iso.org/obp/ui/#iso:std:iso-iec:9899:ed-3:v1:en
編集:コメントに基づいて、NULLをすでにfree
dに変更しました。また、リンクはISO/IEC 9899:2011(en)を指すようになりました