2

VS2010 Windows 7 で c++ を書いています。サイズ 64 バイトのファイルを読み込もうとしています。コードは次のとおりです。

    BYTE* MyReadFile(FILE *f)
{
    size_t result;
    BYTE *buffer;
    long lSize;
    if (f == NULL) 
    {
        fputs ("File error", stderr); 
        exit (1);
    }

    fseek (f, 0, SEEK_END);
    lSize = ftell (f);
    rewind (f);

    //buffer = (BYTE*) malloc (sizeof(char)*lSize);
    buffer = new BYTE[lSize];
    if (buffer == NULL) 
    {
        fputs ("Memory error", stderr); 
        exit (2);
    }

    result = fread (buffer, 1, lSize, f);
    if (result != lSize) 
    {
        fputs ("Reading error",stderr); 
        exit (3);
    }

    fclose (f);
    return buffer;
}

ファイルサイズを取得すると64ですが、新しいBYTE [lSize]でメモリを割り当てると80バイトのスペースが得られるため、奇妙なシーケンスээээ««««««««оюоюがバッファの最後に追加されます。これを処理する方法を教えてください。

4

4 に答える 4

4

コードが割り当てられたメモリの境界を超えていないかどうかを確認するために使用されます。プログラムがこの値を上書きすると、CRT ライブラリはバッファを解放するときにデバッグ メッセージを報告します。

ここを見てください:http://msdn.microsoft.com/en-us/library/ms220938%28v=vs.80%29.aspx

ここに画像の説明を入力

于 2012-02-22T07:57:18.053 に答える
4

割り当てたバイト数と表示されるバイト数には重要な違いがあります。

lsize が 64 の場合、実際に 64 バイトを割り当てたことになります。これは、画面の背後で C++ ランタイムが正確に 64 バイトを Windows に要求したという意味ではありません。実際には、メモリ管理者は、自分で宿題をすることができるように、わずかに多くのメモリを要求します。多くの場合、これらの余分なバイトは、new/malloc から返されるポインターの前に割り当てられるため、表示されることはありません。

しかし、それはあなたの問題ではありません。問題は、fread を使用してファイルから 64 バイトを読み取ることです。どのような種類のデータを読み取っているのかを fread が知る方法はありません。構造体、char バッファー、double のセットなどの可能性があります。これらのバイトを読み取るだけです。

これは、ファイルに文字 "ABC" が含まれている場合、正確に "ABC" が返されることを意味します。ただし、C では、文字列はヌル文字で終了する必要があるため、このバッファーを printf に渡すと、ヌル文字が見つかるまでメモリをスキャンし続けます。

したがって、問題を解決するには、次のように 1 バイト多く割り当て、最後のバイトをヌル文字に設定します。

buffer = new BYTE[lSize+1]; 
buffer[lSize] = '\0';
于 2012-02-22T07:58:42.267 に答える
3

これはメモリの問題のように見えるかもしれませんが、実際には印刷の問題です (@Mystical が指摘したように)。何かを文字列として出力する場合は、ヌル終端を配置する必要があります。そうしないと、メモリが検出されるまで (UB) 乱暴に読み取られます。

代わりにこれを試してください:

buffer = new BYTE[lSize + 1];
if (buffer == NULL) 
{
    fputs ("Memory error", stderr); 
    exit (2);
}

result = fread (buffer, 1, lSize, f);
if (result != lSize) 
{
    fputs ("Reading error",stderr); 
    exit (3);
}

buffer[lSize] = '\0';

返されたバッファの最後にヌル ターミネータがあることを確認します。

于 2012-02-22T07:57:06.697 に答える
1

メモリが割り当てられるとき、バイト単位ではありません。代わりに、8 バイトまたは 16 バイトのアラインされたブロックに割り当てられます (ポインターの前の先頭にヘッダーがある可能性があります)。これは、多数 (数百万) の小さなオブジェクトを作成しない限り、通常は問題になりません。これは、C では問題になる必要はなく、Java (オブジェクトの配列またはスタックに割り当てられたオブジェクトをサポートしていない) でも大きな問題ではありません。

于 2012-02-22T07:52:43.430 に答える