読者です 読者をやめる 読者になる 読者になる

TLS Callbacks

id:NyaRuRu:20051220#p2 続編.

Windows Server 2003以降(これにはWindows XP Professional x64 Editionも含まれる)のOSでは、FlsAllocを使用することで、ファイバ終了時にOSからコールバックを受けることができるようになりました。ファイバローカルストレージ(FLS)は、ファイバを全く使用しない場合でもTLSの代用として使用できます。そのためVisual C++ .NET 2003のCRTやVisual C++ 2005のCRTは、可能であればファイバローカルストレージを利用することで、確実に管理ブロックを開放するようになっています。このような重要なコールバックメカニズムが、従来のTLSには欠如していたと言えるでしょう。

ごめんなさい,Win32 Thread Local Storage (TLS) にコールバックメカニズムは存在して,google:"TLS Callbacks" というのがあるようです*1
TLS Callbacks は PE ヘッダ中にコールバック関数を登録しておくことで EXE ファイルでも DllMain 相当の通知を受けられるというものです.
http://www.interq.or.jp/chubu/r6/reasm/PE_FORMAT/6_6_2.html
Windows 2000Windows XP では以下のコードを付け足すことでサンプルプログラムでもメモリリークが発生しなくなることを確認しました.

namespace 
{ 
    extern "C" void __cdecl _freeptd (void *);
    void NTAPI tls_callback( void*, DWORD dwReason, void* ) 
    { 
        if(dwReason == DLL_THREAD_DETACH) 
        {
            _freeptd(NULL);
        }
    } 

    // Add callback to the TLS callback list in TLS directory.
    #pragma data_seg(push, old_seg)
    #pragma data_seg(".CRT$XLB")
    DWORD tls_callback_ptr = (DWORD)tls_callback;
    #pragma data_seg(pop, old_seg)

    extern "C" int _tls_used;
    int dummy() {
        return _tls_used;
    }
}

また Windows 98 SE で TLS Callbacks が呼び出されないことを確認しました.

Thread-Local-Storage Callbacks are a seldom used feature of Portable Executables. Many compilers and linkers, including Microsoft's, do not fully support TLS callbacks, or have a buggy implementation. Furthermore, they are not universally supported on all Windows platforms. Win9x does not execute them under all conditions (i.e. program load), while WinNT does.

とあるように,Windows 9x では TLS Callbacks はサポートされていないようです.
CodeZine の記事は月曜にでも訂正入れておきます.

*1:TLS Callbacks の存在については boost ML の「Windows MSVC thread exit handler for staticly linked Boost.Thread」での議論で知りました.このあたりは正直 Advanced Windows でも足りてない感じです.