編集:(チャールズ・ベイリーに)もう少しこの回答を議論した、私はそれは、ブーストの実装::機能に依存しますので、これは安全ではないと信じています。
我々はこのようなものになりますactual_foo入力し、コールスタック:actual_fooの実行が完了したときに
actual_foo
boost::function::operator()
main
だから、我々は
boost::function
の
operator()
コードに戻ってジャンプし、このオブジェクトが削除されました。これは問題であることは保証されていません - それは
delete this
を呼び出すようなビットですが、削除されたオブジェクトのメンバ関数で行うことを非常に慎重にする必要があります。仮想関数を呼び出したり、データメンバーを使用することはできません。
問題は、ラップされた関数がoperator()
で実行されていることを保証していないことに気付いていません。私のプラットフォームでは危険なことは何もしていないようです(valgrindは不平を言っていません)が、別のプラットフォームで、異なる実装で、あるいは別のコンパイルフラグを使って、オブジェクトが削除されると許可されません。例えば、メンバ変数を使ってデバッグ情報を書き出すことができます。
私はこれが危険なことであると信じています。これは特定の状況下では未定義の動作を引き起こす可能性があります。
さらに注:
私はそれが関数ポインタを呼び出した後、実際にやっているブーストで簡単に見てました。ここでは:のoperator()関数の687行で、私の解釈はすぐに戻り値を返し、何もしないので、実際には、その実装では、あなたはokですが、それに関するコメントまだ危険なままである。私はこれがOKであると信じて
:以下
オリジナルの答え...私は非常によく、コードの間違ったビットを見つけ、および/またはそれが間違って理解している可能性があることに注意してください。 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のように)、この関数オブジェクトの自動削除を使用することをお勧めします。より清潔で、安全で、恐ろしくなく、例外的に安全です。しかし、私はあなたがすでにそのことをすべて知っていると確信しています。コードをそのまま生かすのがよい理由があります。
要約すると、実装のoperator()呼び出しが何をするかによって危険かもしれません。 。あなたは何をしているのか保証していないので、それは危険です。 boost :: functionの現在の実装は安全です。 –