1

ccppc (バージョン 3.3-e500) でいくつかの C ソース ファイルをコンパイルしようとしています。ほとんどの場合、コンパイルは失敗し、次のエラーが表示されます。

0 [main] cc1 {PID} sigproc_init: cannot create wait_sig thread, Win32 Error 8

この Win32 エラーを調べたところ、ERROR_NOT_ENOUGH_MEMORY. 物理メモリの問題ではないことは確かです。このマシンには 4GB があり、コンパイル時に使用されるのは 1.5GB 以下です。残念ながら、私のマシンにはローカル管理者がいないため、ページファイルの問題を調査できません。

いくつかの失敗の後、ソースは最終的にコンパイルされ、すべてのソースがコンパイルされると、出力された.o's に明らかな問題はありません。ただし、この問題により、10 分のビルドが 1 時間以上のビルドに変わります。

この問題は XP x86 マシンには存在しません。私は、どちらの OS についても x64 を調査していません。

Windows 7 の ccppc やその他の gcc バイナリでこのような問題に遭遇した人はいますか? 解決策を見つけるためのガイダンスは素晴らしいでしょう。

4

2 に答える 2

2

Windows XP 32 ビットでのコンパイルから Windows 7 64 ビットへのコンパイルの移行時に、PowerPC の gcc 2.96 からの cc1.exe プログラムが一部のコンパイルで同じエラーで失敗することがわかりました。Visual Studio Debugger を使用して cc1.exe にアタッチし、Sysinternals ツールで監視した調査では、次のことがわかりました。

  1. cc1.exe プログラムが成功すると、3 つのスレッドが生成されます。

  2. cc1.exe プログラムが失敗すると、3 回目の CreateThread() 呼び出しが で失敗しましERROR_NOT_ENOUGH_MEMORYた。

  3. Visual Studio コマンドを実行して報告された cc1.exe のイメージ ヘッダーはdumpbin /HEADERS、スタック予約サイズが 400000000 バイトであることを示していました。つまり、作成された各スレッドには、400000000 バイトの連続した仮想アドレス空間が必要です。

  4. CreateThread 呼び出しが で失敗したERROR_NOT_ENOUGH_MEMORY場合、Sysinternals VMMap ツールは、最大空き仮想メモリ領域が、要求されたスタック予約サイズである 400000000 バイト未満であることを示しました。

  5. cc1.exe は 32 ビット プロセスで、2G バイトの仮想アドレス空間があります。Windows 7 には ASLR (アドレス空間レイアウトのランダム化) があり、DLL のロード アドレスがランダム化されます。ASLR は仮想アドレス空間を効果的に断片化していると思います。これにより、cc1.exe プロセスの一部の呼び出しで、ロードされた DLL によって使用される仮想アドレスが、スレッド スタック用に十分な大きさの空き領域を残しません。ASLR と同様に、Windows 7 では cc1.exe に読み込まれる DLL が Windows XP の約 4 倍であり、これが問題の原因となっている可能性があります。

上記の調査に基づいて、Visual Studioeditbin /STACK:67108864プログラムを使用して、cc1.exe のスタック予約サイズを 64M バイトに減らしました。64M バイトは、C++ コードに使用される cc1plus.exe プログラムのスタック予約サイズとして選択されたものです。スタック予約サイズの縮小により、ERROR_NOT_ENOUGH_MEMORYエラーは再び見られなくなりました。

于 2015-12-11T10:41:33.963 に答える