編集:この回答について (Charles Bailey と) もう少し議論しましたが、boost::function の実装に依存しているため、これは安全ではないと思います。
actual_foo に入ったときのコール スタックは次のようになります。
actual_foo
boost::function::operator()
main
したがって、actual_foo の実行が終了すると、 のoperator()
コードに戻りboost::function
ます。このオブジェクトは削除されています。これは問題であるとは限りません。呼び出しに少し似delete this
ていますが、削除されたオブジェクトのメンバー関数で行うことには十分注意する必要があります。仮想関数を呼び出したり、データ メンバーを使用したりすることはできません。
問題は、それがラップする関数が呼び出された後に何をboost::function
するかについて何の保証もしていないことに気づいていないことです。operator()
私のプラットフォームでは危険なことは何もしていないようです (そのため、valgrind は文句を言いません)。オブジェクトが削除された後は許可されません。たとえば、メンバー変数を使用してデバッグ情報を書き出す可能性があります。
したがって、これは特定の状況下で未定義の動作を引き起こす可能性がある危険なことだと思います。
さらに注意:
関数ポインターを呼び出した後、ブーストが実際に何をしているのかを簡単に調べました。ここを見る: http://boost.cvs.sourceforge.net/viewvc/boost/boost/boost/function/function_template.hpp?view=markup 687 行目の operator() 関数で、私の解釈では、すぐに戻り値であり、他には何もしないので、実際には、その実装で問題ないはずですが、それについてのコメントは依然として危険です. 間違ったコードを見つけたり、間違って理解したりする可能性が非常に高いことに注意してください...
以下の元の回答:
これでいいと思います。に入るactual_foo
までに、 オブジェクトboost::bind
とboost::function
オブジェクトはジョブを終了し、実際の関数 を実行していますactual_foo
。
valgrindを介してプログラムを実行することにより、プラットフォーム (gcc 4.2.4、Linux) でこれをチェックアウトしました。
これが私が実行したプログラムです:
#include <boost/bind.hpp>
#include <boost/function.hpp>
class Magic
{
public:
int magic( int i )
{
return 5;
}
};
typedef boost::function<int(int)> foo_type;
foo_type* global_foo = NULL;
int actual_foo( int i, Magic* m )
{
delete global_foo;
return m->magic(i);
}
int main()
{
Magic m;
global_foo = new foo_type( boost::bind( &actual_foo, _1, &m ) );
return (*global_foo)(10);
}
valgrind の出力は次のとおりです。
$ valgrind ./boost_bind
==17606== Memcheck, a memory error detector.
==17606== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==17606== Using LibVEX rev 1804, a library for dynamic binary translation.
==17606== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==17606== Using valgrind-3.3.0-Debian, a dynamic binary instrumentation framework.
==17606== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==17606== For more details, rerun with: -v
==17606==
==17606==
==17606== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 17 from 1)
==17606== malloc/free: in use at exit: 0 bytes in 0 blocks.
==17606== malloc/free: 1 allocs, 1 frees, 16 bytes allocated.
==17606== For counts of detected errors, rerun with: -v
==17606== All heap blocks were freed -- no leaks are possible.
しかし、これは奇妙なことだと言わざるを得ません。可能であれば、この関数オブジェクトをスタック変数にするか、スタック変数のデストラクタで削除する ( RAIIのように) ことにより、この関数オブジェクトの自動削除を使用することをお勧めします。それはよりきれいで、より安全で、怖くなく、より例外的に安全です。しかし、あなたはすでにそれをすべて知っていると確信しており、コードをそのまま使用する正当な理由があります。