web-dev-qa-db-ja.com

reallocを使用して割り当てられたメモリを縮小する

Cのrealloc関数に関する簡単な質問:reallocを使用して、ポインターが指しているメモリブロックを縮小すると、「余分な」メモリが解放されますか?それとも、どういうわけか手動で解放する必要がありますか?

たとえば、私が

int *myPointer = malloc(100*sizeof(int));
myPointer = realloc(myPointer,50*sizeof(int));
free(myPointer);

メモリリークは発生しますか?

27

いいえ、メモリリークは発生しません。 reallocは、将来のmalloc操作で残りを「使用可能」とマークするだけです。

ただし、後でfreemyPointerを実行する必要があります。余談ですが、0reallocのサイズと同じで、freeと同じ効果があります一部の実装では。 Steve JessopとR.がコメントで言ったように、あなたはそれに頼るべきではありません。

20
cnicutar

確実にメモリリークはありませんが、reallocを呼び出してサイズを小さくすると、少なくとも3つのことが起こります。

  1. 実装は、割り当てられたメモリブロックを新しく要求された長さで分割し、最後に未使用部分を解放します。
  2. 実装は、新しいサイズで新しい割り当てを行い、古いコンテンツを新しい場所にコピーし、古い割り当て全体を解放します。
  3. 実装は何もしません。

オプション3はやや悪い実装ですが、完全に合法です。後でfreeを呼び出してもすべてが解放されるため、「メモリリーク」はまだありません。

オプション1と2については、パフォーマンスを優先するか、メモリの断片化を回避するかに大きく依存します。私は、ほとんどの実際の実装はオプション1の実行に傾くと思います。

15
R..

新しいコードは、reallocが失敗した場合でも元の割り当てをリークします。ほとんどの実装ではブロックの縮小に失敗しないと思いますが、それは許可されています。ブロックの拡大または縮小にかかわらず、reallocを呼び出す正しい方法はvoid * tmp = realloc(myPointer、50 * sizeof(int));です。 if(!tmp){/ *どういうわけかエラーを処理します。 myPointerは、まだ割り当てられている古いブロックをまだ指しています* /} myPointer = tmp;。 – 48分前のスティーブジェソップ

こんにちは、コメントへの返信方法がわかりませんでした。

TmpをmyPointerのタイプにキャストする必要がありますか?この場合、私は書く必要がありますか

myPointer = (int*)tmp

また、この場合、free(myPointer)を実行すると、tmpが指すメモリも解放されますよね?だからする必要はありません

free(myPointer)
free(tmp)
4
azphare

あなたがあなたのコードを与えた方法で、はい、それはリークを持っているかもしれません。 reallocの考え方は、データの新しい場所を返すことができるということです。あなたが質問でそれをするように、reallocがあなたに送るそのポインタを失います。

int *myPointer2 = realloc(myPointer,50*sizeof(int));
assert(myPointer2); 
myPointer = myPointer2;
3
Jens Gustedt