スレッド関数内の auto 変数
初回ということで、 id にちなんで std::auto_ptr で痛い目に遭った経験を。
どのくらい有名な話かわからないのですが、 _endthread() などをスレッド関数の中から呼び出した場合、スレッド関数のスコープ内にある auto 変数は解放されません。つまり、 auto_ptr または自作スマートポインタが機能しなくなるのです。ローカル変数の解放をスマートポインタに任せていると全てリークします。
サンプルコード
#include <stdio.h> #include <process.h> #include <memory> class Test { public : Test() { printf( "Test new\n" ); } virtual ~Test() { printf( "Test delete\n" ); } }; void testThread( void* param ) { std::auto_ptr< Test > test( new Test ); _endthread(); } void main() { _beginthread( testThread, 0, NULL ); getchar(); }
実行結果
Test new
このように、 Test クラスのデストラクタは実行されません。スレッド終了に _endthreadex() / ExitThread() を使った場合も同様です。
対策として最も楽な方法は、スレッド関数の中でスコープを切ってやることです。
void testThread( void* param ) { { std::auto_ptr< Test > test( new Test ); } _endthread(); }
実行結果
Test new Test delete
こうすれば、 _endthread() 前にスコープの終了が来るので、その時点でスマートポインタが解放されます。つまり、スレッド終了関数をコールする前に必ずスコープを切っておけば OK です。
なお、「スレッド関数の中で goto を使っている場合はどうすればいいか」は考えていませんので悪しからず。スマートポインタと goto を併用するような真似はやめましょうとしか言えません。