2011/08/18 [木]
Windows では、スレッド毎に固有の記憶領域(TLS)を持たせることができます。C や C++ では、変数に __declspec(thread) 修飾をすることで行えます。この記憶領域を持った Visual C++ / MSC でコンパイルされた DLL を呼び出す場合、DLL がアプリケーションに静的にリンクされていた場合(OS がアプリケーションと同時に読み込む場合)、問題なく動きます。しかし、LoadLibrary を使って読み込んだ DLL の場合、Windows Vista / Windows Server 2008 より前の OS では問題が生じます。
環境 | DLL読込 | 問題 |
---|---|---|
Win32s | 不可 | − |
Win95 | 不可 | − |
Windows 98 / NT | ○ | 変数の値が不定 |
Windows 2000 / Server 2003 / XP | ○ | 変数の参照で例外発生 |
Windows Vista / Server 2008 / 7 | ○ | なし |
bcc32 | ○ | なし(独自回避) |
これは、OS がアプリケーション起動時に、DLL の分も含めてまとめて TLS 領域を確保することから起こる問題です。後からロードされるとその領域を拡張できないので、対応できないということのようです。そのため、ロードする場合には、DLL 側で手動で TlsAlloc などを使う必要があります。bcc32 の場合は回避ルーチンが入っているので、何も考えることなく使用できます。
- 参考
- PRB: Calling LoadLibrary() to Load a DLL That Has Static TLS
- Rules and Limitations for TLS
- LoadLibrary Function (Windows)
- Thread Local Storage, part 6: Design problems with the Windows Server 2003 (and earlier) approach to implicit TLS
- Thread Local Storage, part 7: Windows Vista support for __declspec(thread) in demand loaded DLLs
by seclan