2016-07-11 9 views
3

size_t型の場合にスローされた理由:行の下 bad_alloc()例外は、私は、コードの下の部分に取り組んでいると私は、このコードを実行していたとき、私は<code>std::bad_alloc</code>例外を取得しています

int _tmain(int argc, _TCHAR* argv[]) 
{ 
FILE * pFile; 

size_t state; 
pFile = fopen("C:\\shared.tmp", "rb"); 
if (pFile != NULL) 
{ 
    size_t rt = fread(&state, sizeof(int), 1, pFile); 
    char *string = NULL; 
    string= new char[state + 1]; 
    fclose(pFile); 
} 
return 0; 
} 

これが原因

例外がスローされる:

string = new char[state + 1]; 

これはどうして起こりますか?これをどうすれば解決できますか?

+0

割り当ての前に状態を印刷して結果を投稿することはできますか? –

+0

デバッガ、ブレークポイント、およびウォッチウィンドウはおそらく、割り当てようとしているものの大きさを伝えます。私のクリスタルボールはサイズが「size_t」と一致しない形式で格納されていると伝えますが、とにかく 'int'のサイズを読んでいるので、とにかくそれを扱いますあなたのプラットフォーム上の 'size_t 'はおそらくそれぞれ32ビットと64ビットです。ああ。 – WhozCraig

+0

エンディアンについては心配しています。このコードは整数型の内部表現をバイト単位で構成するのではなく、直接読み込むためです。 OPは彼が値 '0x000000FF'の整数を読み込んでいると思うかもしれませんが、代わりに' 0xFF0000000'を得ているかもしれません! – Hurkyl

答えて

7

あなたが初期化されていない64ビットのアドレスを渡しているが(現代の64ビットシステムでは8バイト)変数、state、及びsizeof(int)(これらの同じシステム上で32ビット、4バイト)を読み取ることfreadを伝えるのバイトファイルをこの変数に追加します。

これは、変数の4バイトを読み込み値で上書きしますが、残りの4つは未初期化のままにします。どの4バイトが上書きされるかは、アーキテクチャによって異なります(インテルCPUでは最も重要ではなく、ビッグエンディアン構成のARMで最も重要です)が、4バイトは初期化されずに何かを含む可能性があるため、 。

あなたのケースでは、最も重要なバイトであり、少なくとも1つの非ゼロビットが含まれている可能性があります。つまり、持っていない4GBを超えるメモリを割り当てようとします。

ソリューションを作ることですstatestd::uint32_t(あなたは明らかにファイルが符号なし整数を表す4つのバイトが含まれていることを期待するので、<cstdint>を含めることを忘れないでください)とsizeof(std::uint32_t)を通過し、そして一般的に確認しているため、すべてのfreadとポインターとサイズを渡す同様の呼び出しでは、ポインターが実際に指しているものが実際に渡すサイズと同じであることを確認します。 size_t*sizeof(int)を渡すことは、64ビットシステムではこれらの要件を満たしておらず、C++の基本型のサイズは保証されていないため、一般的にバイナリ入出力には使用したくありません。

+0

私はstd :: uint32_tを使ってみましたが、まだ同じbad_alloc()エラーが発生しています。フリーダイヤル後の状態値を参照してください - "3435973238"(これはsize_tと一緒にあります)。 std :: uint32を使用すると、これより高い値になります。実際に私の問題は、私の "状態"変数がfread()関数から初期化されていないということでした。 –

0

割り当てようとしている文字の最大数は何かを決定し、stateがそれより大きい場合はエラーを出します。ほぼ確実です。

1

あなたはC++コードに向上させることができ、様々なものがありますが、あなたは、この動作になってしまう理由の数、そこにされています、変数state

まずタイプsize_tのですが、あなたのコードはfread(&state, sizeof(int), 1, pFile);を使用してその値を初期化しようとします。今、sizeof(state) != sizeof(int)の場合、未定義の動作があります。 sizeof(state) < sizeof(int)の場合、fread文は通常、変数stateの格納後に任意のメモリを上書きします。これにより、未定義の動作が発生します(例:stateはランダムな大きな値を持つ可能性があり、割り当てに失敗します)。

第二に、sizeof(state) > sizeof(int)場合、stateは、部分的にのみ初期化され、その実際の値は、(freadによって)初期化され、初期化されていないビットの両方に依存します。したがって、その値は大きくなり、割り当てが失敗する可能性があります。

第3の場合、sizeof(state) == sizeof(int)の場合、読み込み値が大きすぎることがあり、メモリー不足のため単に割り当てが失敗する可能性があります。

第4に、ファイルから読み込んだ値が、エンコードまたはエンディアンが異なる可能性があります。たとえば、値がビッグエンディアン形式でファイルに書き込まれ、リトルエンディアンCPUでfreadの場合、バイトが正しくスワップされない可能性があります。読み取られた値を使用する前に、バイトをスワップする必要があるかもしれません。

私はあなたの代わりにfread(&state, sizeof(state), 1, pFile);を使用して値を読み取り、変数stateこのようなstd::uint64_tとして、<cstdint>(またはプレC++ 11用<stdint.h>)から、いくつかの固定幅整数型を使用することをお勧めし、その後バイトスワップstate場合CPUのエンディアンがファイルに格納されている値のエンディアンと一致しません。

関連する問題