3

私は、メモリに約 220 mln の短い値の配列を格納するプログラムに取り組んでいます。このデータ ブロックは次のように割り当てられます。

short * arrayName = new short[SIZE_OF_ARRAY];

次に、ファイルの内容がメモリに読み込まれます。チーム内の別の人物がプログラムの全体的なアーキテクチャを大幅に更新した後、この正確な行でプログラムがクラッシュし始めました。メッセージは次のとおりです。

Microsoft Visual C++ Runtime Library
Runtime Error!
abnormal program termination

これは、このメモリ割り当ての呼び出しですぐに発生します (ポインターが NULL かどうかを確認するためのチェックなど、それ以上の行は実行されません)。数日経っても、この行がこのように動作し始めた原因となった他のコードの変更が正確にはわかりません (実際には、この配列にリモートでリンクされているものは何も変更されていません)。

Linux (正確には Ubuntu) では、すべて正常に動作しています。この問題は、Windows マシンにのみ存在します。64 ビットの Windows OS では、この回避策が役立ちます (.pro ファイル内):

QMAKE_LFLAGS_WINDOWS += /LARGEADDRESSAWARE

32 ビットでは、役に立ちません。

次の方法で行を malloc に置き換えると、その後のポインターが NULL であるかどうかを確認し (これはそうです)、errno からエラー コードを取得することができました。これは 12 (ENOMEM) = "メモリが不足しています" です。

short * arrayName = (short *)malloc(SIZE_OF_ARRAY * sizeof(short));

この StackOverflow の質問は、同じ問題に関するものと思われます。その類似性は、より少ない量のメモリの割り当てが機能するという点までです (ただし、450 MB は機能しません)。そこの回答は、メモリの断片化が激しく、 new / malloc が連続したメモリ領域を割り当てることができないことを示唆していましたが、私の場合、2 つの物理 GB (および 4 つの仮想 GB) のうち最大 600 MB のみが再起動された後でも、問題は引き続き発生します。使用されているため、多少除外されています (さらに、前述のように、まったく同じコード行が以前に機能していました)。

私の主な疑いは、それがヒープサイズと関係があるということです(ただし、 new と malloc の両方がメモリをヒープに割り当てるかどうかはわかりません;また、Qtでヒープサイズを変更する方法をまだ見つけていません)。ここで何か不足していますか?

4

1 に答える 1

2

RAM の不足ではなく、アドレス空間の不足が原因で、メモリの割り当てが失敗します。RAM が不足すると、プログラムが遅くなり、プログラムがディスクにページ アウトされるため、多くのディスク スラッシングが発生します。

/LARGEADDRESSAWAREアプリがより大きなアドレス空間を受け入れることができることを OS に伝えます。Win64 は Win32 アプリに 3GB のアドレス空間を提供しますが、Win32 ではこれは標準ではありません。

ASLR をオフにすると、DLL が直線的に読み込まれるため (セキュリティ リスクである予測可能なオフセットで)、役立つ場合があります。ASLR を使用すると、DLL がメモリ内に分散されます。2 GB のアドレス空間に 10 個の DLL しか分散していない場合 (これは非現実的なほど少ない)、それらの間の平均空間は ~200 MB です。

于 2013-08-12T08:30:24.417 に答える