最初の質問:
realloc(array, 0)
と同等ではありませんfree(array)
。
標準 (C99、§7.20.3.4 ¶1) は次のように述べています。
このrealloc
関数は、 が指す古いオブジェクトの割り当てを解除し、ptr
で指定されたサイズの新しいオブジェクトへのポインターを返しますsize
。
size==0
;の「特別なケース」はありません。したがって、サイズがゼロのオブジェクトへのポインターを取得していますが、これはまだオブジェクトである可能性があり、解放する必要があります。
realloc
興味深いことに、はそのような状況では単純に失敗して を返す可能性があると思いますNULL
。この場合、コード内でメモリがリークされます。realloc
失敗すると、渡した元のメモリ ブロックが解放されないためです (これが決して解放しない理由ですarray = realloc(array, size)
が、常に中間変数を使用しNULL
て順番にチェックします)。メモリリークを避けるため)。
実際、標準では、私が覚えているsize==0
だけでなく、すべてのメモリ割り当て関数に対して実装定義の動作を指定しています。malloc
したがって、以下に説明するように、動作は実装定義です。
より直感的には、他のポインターの+ +realloc
と「概念的に同等」であり、メモリの 0 バイトのチャンクを -ing すると、何も格納するために使用されない一意のポインターが返されます (0 バイトを要求しました)。まだ編集されていません。したがって、いいえ、そのように使用しないでください。一部の実装 (つまり、Linux) で動作する可能性がありますが、保証されていません。malloc
memcpy
free
malloc
NULL
free
realloc
また、それが機能しないとどのように推測したかは明確でfree
はありません。あなたがこれを確信したかもしれない2つの方法を考えることができます:
array
およびそれが指すデータの値は変更されません。
- タスクマネージャーで割り当てられたメモリ/
top
/何でも減少しません。
最初のケースでは、それは正常です。ポインターを解放しても、魔法のように消去されることはありません。ポインターはポインターが指している場所を指し続けますが、そのメモリーはもはやあなたのものではありません。C ランタイムに戻っており、おそらく将来的には再び解放されるでしょう。malloc
. そのため、そのことは「ダングリング ポインター」と呼ばれ、多くの人は、既に解放されているメモリのスペースに再び書き込むことを避けるために、free
それを設定した後です。NULL
2 つ目については、アロケーターがすぐにオペレーティング システムにメモリを返さないというのが一般的なポリシーです (非常に大きなチャンクについて話している場合を除きます)。おそらく、アプリケーションはすぐにそのようなメモリを必要とし、現在のプロセスのためにそのメモリを保持することで、OS からメモリを取得/提供するための連続的なシステム コールを回避できるという考えです。通常使用されるメモリを監視するためのシステム ユーティリティは、OS がプロセスに与えたものしか見ることができないため、メモリ使用量の減少が見られないのは正常です。
ちなみに、 でchar ** array
割り当てられたものへのポインタが含まれている場合malloc
は、最初にfree
それらにアクセスする必要があります。そうしないと、メモリリークが発生します。
2 番目の質問:
C 文字列は null で終了します。つまり、文字列の最後の文字は常に\0
文字列の終わりを示すastrlen
であり、null ターミネータを除いた文字列の長さを示します。そのため、追加しないと、実際に文字列を格納するために必要なメモリよりも+1
1 つ少なく割り当てられます。char
補遺
動作しないということは、クラッシュしたことを意味します(問題は別の場所にある可能性があります)が、使用済みの動的使用メモリを削除するという意味で、それを realloc(X, 0) に変更すると動作しました
マンページにあるように、
malloc()、calloc()、realloc()、または free() でのクラッシュは、ほとんどの場合、割り当てられたチャンクのオーバーフローや同じポインターの 2 回の解放など、ヒープの破損に関連しています。
コードに他のバグがある可能性がありますが、それを見なければ、どこで何が問題なのかを判断することはできません。