41

私は読んでいてrealloc、そこで言及されている点について混乱しました。以下のコードを検討してください。

#include <stdio.h>
#include <stdlib.h>

int main () {

    int* ptr = NULL;
    ptr = realloc(ptr, 10*sizeof(int));
    return 0;
}

realloc初期値を使用してNULLメモリを割り当てることに危険はありますptrか? 代わりに:

int* ptr = NULL;

私はこれを持っていました:

int* ptr; // no value given to ptr

reallocを使用して呼び出すのは問題でしょptrうか?

4

3 に答える 3

54

最初にNULL値のptrを使用してreallocでメモリを割り当てることに危険はありますか

なし

7.22.3.5

ptr がヌル ポインターの場合、realloc 関数は、指定されたサイズに対して malloc 関数のように動作します。

2 番目の部分:

int* ptr; // no value given to ptr

ptr を使用して realloc を呼び出すのは問題でしょうか?

初期化されていないポインタを使用している場合、その値がどうなるか予測できないため、これは非常に深刻な問題です。この関数は、 /から取得した値reallocに対してのみ正しく機能します。NULLmallocrealloc

それ以外の場合、ptr がメモリ管理関数によって以前に返されたポインターと一致しない場合 [...] 動作は未定義です

于 2012-08-26T22:14:23.557 に答える
10

示されている特定のコードでは、最初にヌル ポインターを使用しても問題はありません。

変数ptrが初期化されていない場合 (0 または NULL に設定されていない場合)、それをrealloc()使用する呼び出しは危険です。動作は定義されておらず、運が良ければプログラムはクラッシュしますが、運が悪ければ、プログラムの後半で問題が発生し、問題を特定するのが困難になるまで、しばらくは機能しているように見えます。ずっと前に実行されたコードで。

malloc()最初の割り当て以降に使用する方が良いと主張する人がいますrealloc()。特に、メモリを解放することができたとしても、メモリを解放するために使用ptr = realloc(ptr, 0);しない可能性があるためです (実際には必要ないmalloc()か、3 つの操作すべてを実行できるfree()ためrealloc())。しかし、C90 標準ではrealloc(0, new_size)と同等に動作する必要malloc(new_size)があり、異なる動作をする C ライブラリを私は知りません (ただし、いくつかあるかもしれません。ほとんどが最も広く使用されているものではありますが、いくつかの C ライブラリしか使用していません)。


ただし、次のコードのようなより一般的なケースでは、コードに微妙な問題があります (ただし、最初の null ポインターには関係ありません)。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    char    *ptr = NULL;
    size_t   len = 0;
    char     buffer[256];

    while (fgets(buffer, sizeof(buffer), stdin))
    {
        size_t buflen = strlen(buffer) + 1;
        if (buflen > len)
        {
            if ((ptr = realloc(ptr, buflen)) == 0)  // Danger!
                // ... handle memory allocation failure ...
            len = buflen;
        }
        strcpy(ptr, buffer);
        // ... do something with ptr
    }
    free(ptr);
    return 0;
}

危険は何ですか?危険なのは、2 回目以降のメモリ割り当てが失敗ptrし、割り当てられたメモリへの唯一のポインタである場合、以前の値を null で上書きすることです。つまり、これ以上使用して割り当てられたメモリを解放することはできませんptr— メモリ リークが発生しました。(最初の割り当てでは、初期値は 0、上書きされた値は 0 で、何も変更されていません。メモリ リークはありません。そのため、コードにループが追加されています。)

経験則

  • 書かないでptr = realloc(ptr, newsize);

テストが完了するまで、新しい値を別の変数に保存します。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    char    *ptr = NULL;
    size_t   len = 0;
    char     buffer[256];

    while (fgets(buffer, sizeof(buffer), stdin))
    {
        size_t buflen = strlen(buffer) + 1;
        if (buflen > len)
        {
            char *new_ptr = realloc(ptr, buflen);
            if (new_ptr == 0)
                // ... handle memory allocation failure ...
            ptr = new_ptr;
            len = buflen;
        }
        strcpy(ptr, buffer);
        // ... do something with ptr
    }
    free(ptr);
    return 0;
}

このコードは、割り当ての失敗時にメモリをリークしません。

補助的な推奨事項: という変数を使用しないでくださいnew。C++ コンパイラでコンパイルするのが難しくなります。今は C++ に変換するつもりがなくても (そして、そうするとメモリ管理を書き直すことになるかもしれませんが)、C++ キーワードnewを C 変数名として使用するメリットはありません...明示的に変換したい場合を除きます。 C++ コンパイラでのコンパイルを防ぎます。

于 2012-08-26T22:56:22.607 に答える
4

最初に NULL 値の ptr を使用して realloc を使用してメモリを割り当てることに危険はありますか?

いいえ、それはまさにmalloc.

代わりに:

int* ptr = NULL;

私はこれを持っていました:

int* ptr; // no value given to ptr

ptr を使用して realloc を呼び出すのは問題でしょうか?

はい、問題があります。reallocが を取得しない場合NULL、その場所から開始してメモリを拡張しようとするか、メモリの別の部分を拡張しようとする場合があります。初期化されていない変数は任意の値を持つことができるため、可能性は非常に高く、好きな値ではありません。運が良ければ、プログラムはすぐにクラッシュします。freemallocrealloc

于 2012-08-26T22:15:31.670 に答える