2014-01-15 41 views
15

私の静的リンクされたVisual C++ 2012プログラムはCRTLエラーを散発的に生成します: "R6016 - スレッドデータ用のスペースが足りません"。エラーR6016の解決 - スレッドデータのための十分なスペースがありません

マイクロソフトの最小限のドキュメントでは、新しいスレッドが生成されたときにこのエラーメッセージが生成されるが、十分なメモリが割り当てられていないと述べています。

しかし、私のコードでは明確に定義された2つのケースで明示的に新しいスレッドが生成されますが、ここではどちらも発生していません(確かにマイクロソフトライブラリが内部でスレッドをうまく生成します)。 1人のユーザーが、プログラムがバックグラウンドで存在したときにこの問題を報告しました。

デフォルトの1MBの予約済みスタックサイズまたはヒープサイズをオーバーライドしていないことがわかりました。プログラムで使用されているメモリの総量は、通常、ごくわずかです(実際のRAMが12GBのシステムでは3MB-10MB 、その半分以上は割り当てられていない)。

これは非常にまれです(私はそれを追跡できないため)、複数のマシンで報告されています。私はこれについてWindows 8.1でしか聞いたことはありませんが、あまり読んでいないでしょう。

このエラーに影響する可能性のあるコンパイラ設定がありますか?またはプログラミングミス?

+0

ワイルド推測:アプリ内のスレッドを終了しますか? – DarkWanderer

+2

明らかに、このエラーはTLSスロットに関連しているようです。 http://support.microsoft.com/kb/126709とhttp://stackoverflow.com/questions/13916171/apache-crashes-with-error-r6016-not-enough-space-for-thread-data?lqを参照してください。 = 1 –

+0

私は同意します。メッセージは「スレッドのためのスペースが不足しています**データ**」であり、スレッド(完全停止)ではありません。スレッドデータは、TlsAlloc関数ファミリを使用してスレッドローカルストレージに割り当てられた領域です。このスペースは非常に限られているので、数個以上のアイテムを格納する必要がある場合は、自分のデータ構造を作成し、このデータ構造へのポインタをTLSに格納することをおすすめします。 –

答えて

2

これは、_beginthreadではなくCreateThreadを呼び出すことによって発生していることが判明しました。 「備考」セクションのマイクロソフトのドキュメントにはCreateThread causes conflicts when using the CRT libraryと記載されていますが、実際に変更を加えても、そのエラーは再び発生しませんでした。

1

WindowsのバージョンがVista以上の場合は、DllMainでTlsAllocを呼び出す必要があります。

implicit TLS handling was rewritten in Windows Vista [...] threadprivate and __declspec(thread) should function correctly in run-time loaded DLLs since then.

BOOL APIENTRY DllMain(HINSTANCE hinstDll, DWORD fdwReason, 
      LPVOID lpvReserved) 
    { 
     static BOOL fFirstProcess = TRUE; 
     BOOL fWin32s = FALSE; 
     DWORD dwVersion = GetVersion(); 
     static DWORD dwIndex; 

     if (!(dwVersion & 0x80000000) && LOBYTE(LOWORD(dwVersion))<4) 
      fWin32s = TRUE; 

     if (dwReason == DLL_PROCESS_ATTACH) { 
      if (fFirstProcess || !fWin32s) { 
       dwIndex = TlsAlloc(); 
      } 
      fFirstProcess = FALSE; 
     } 

    } 

kb 118816

When a program is started the size of the TLS is determined by taking into account the TLS size required by the executable as well as the TLS requirements of all other implicitly loaded DLLs. When you load another DLL dynamically with LoadLibrary or unload it with FreeLibrary, the system has to examine all running threads and to enlarge or compact their TLS storage accordingly.

あなたDLLコードは、DLLはLoadLibraryのがロードされる場合TlsAllocようなTLS機能を使用すること、およびTLSを割り当てるように改変されなければなりません。または、__declspec(スレッド)を使用しているDLLは、暗黙的にアプリケーションにロードする必要があります。

ボトムライン:LoadLibraryはスレッドセーフではありません。

+0

提案していただきありがとうございますが、プログラムにはDLLがありません。 – Dev93

0

私はプロセスが32ビットであることを発見しました。私は、コマンドを処理するためのメモリを増やすこの場合

bcdedit /set increaseuserva 3072

関連する問題