5

重複の可能性:
Reallocがポインターの配列のサイズを変更していません

誰かが私の間違いがどこにあるか教えてもらえますか?この関数は、から提供される文字の配列を作成する必要がありstdinます。関連する質問をいくつか読みましたが、複雑すぎて理解できませんでした。

char *readChar(void)
{
    int c;
    int len = 0;
    char* parr = malloc(sizeof(char));

    while((c = getchar()) != EOF)
    {
        ++len;
        int size = sizeof(char)*len;
        parr = (char *) realloc(parr,size);
        *(parr+size-1) = (char) c;
        printf("Done! Size should be: %dB, but real size is %dB\n",size,sizeof(parr));
    }

    return parr;
}

出力:

終わり!サイズは1Bである必要がありますが、実際のサイズは8Bです。サイズは2Bである必要がありますが、実際のサイズは8Bです。サイズは3Bである必要がありますが、実際のサイズは8Bです。サイズは4Bである必要がありますが、実際のサイズは8Bです。

4

5 に答える 5

8

間違いは、sizeof()割り当てたバイト数がわからないことです。それはあなたにサイズを教えてくれますchar *

あなたが望んでいたのは、正しい量のメモリを割り当てたことを確認することだったようです。sizeof()あなたにその情報を与えることはありません。この時点では低レベルの詳細にあります。その情報を見つけるには、OSに依存する何かを行う必要があります。(たとえば、Linuxカーネルでは、kmalloc()メモリを使用ksize()して、取得したバイト数を正確に調べることができます)

于 2012-10-10T18:33:35.007 に答える
2

sizeof(parr)は割り当てられたスペースの量ではなく、char*parrのデータ型)のサイズです。割り当てたメモリの量を知る唯一のポータブルな方法は、自分でそれを追跡することです。

それが期待どおりに機能していると仮定すると、realloc割り当てたバイト数は変数と等しくなりますsize

私があなたのコードで気づいた他のいくつかのこと:

    char* parr = malloc(sizeof(char));

の戻り値を常にチェックしmallocて、成功したことを確認する必要があります。

 char* parr;
 if(!(par = malloc(sizeof(char)))
 {
     //allocation failed
 }

私の目を引いたあなたのコードの次の部分:

 int size = sizeof(char)*len;

これは実際には必要ありません。は常に1バイトに等しいので、ループの各反復で等しい新しい変数を宣言する代わりにsizeof(char)、の現在の値を使用する方がよいでしょう。lenlen * 1

  parr = (char *) realloc(parr,size);

前述のように、と同等であるため、使用する必要はありませsizelen。また、Cでは、一般にポインタをキャストすることはお勧めできません。失敗した場合に備えて、reallocの戻り値も確認する必要があります。

if(!(parr = realloc(parr, size)))
{
    //allocation failed
}

realloc最後の注意として、潜在的なメモリの問題を回避するために、関数を使用するときは常にバッファを使用します。これがあなたのコードの私のスピンです:

char *readChar(void)
{
    int c, len = 0;
    char* parr = NULL, char *tmp;

    if(!(parr = malloc(sizeof(char)))
    {
        fputs("memory allocation failed", stderr);
        exit(1);
    }

    while((c = getchar()) != EOF)
    {
        ++len;
        if(!(tmp = realloc(parr, len)))
        {
            free(parr);
            fputs("memory allocation failed", stderr);
            exit(1);
        }
        parr = tmp;
        *(parr+len-1) = (char) c;
    }
    return parr;
}
于 2012-10-10T18:33:40.607 に答える
1

sizeof(parr)ポインタサイズ(システムでは8バイト)を返します。実際の文字列サイズを確認するには、を使用する必要がありますstrlen(文字列は、\0つまりnullで終了する必要があります)。

于 2012-10-10T18:34:03.880 に答える
1

sizeof()はコンパイル中に評価されるため、動的に割り当てられた配列のサイズを測定することはできません。そして、あなたの例では、x64アーキテクチャでは8Bであるポインタのサイズを使用しています。

于 2012-10-10T18:34:44.177 に答える
1

それはあなたsizeofが印刷するたびに常に同じであるポインタをあなたに与えます。

ポインタが指すメモリのサイズを知る方法はありません。自分でそれらを追跡する必要があります。

余談ですが、常に1であることが保証されています。したがって、とsizeof(char)への呼び出しでそれらを削除できます。安全のために、mallocとreallocの戻り値も確認する必要があります。reallocmalloc

于 2012-10-10T18:35:17.873 に答える