2013-10-09 14 views
5

私はメモリが豊富なアプリケーションで、メモリ不足の状況を適切に処理する必要があります。クロージャのキャプチャされた変数はどこに格納されていますか?

私は、

class memory_manager { 
    // returns true if slot created (and function is being run) 
    // false otherwise 
    static bool create_slot(int id, std::function<void (slot&)>); ........ 
} 

このクラスのハンドル、ログ、およびので、メモリー不足の問題のすべてのようなものを持っているが、スロットの全ての所有権を保持し、同時実行を駆動します。

しかし、私は、次のコードに未処理std::bad_allocあります

slot_data_to_copy dat; 

memory_manager::create_slot(100, [&dat](slot& sx) { sx.assign_data(dat); }); 

は私が投げ変数をキャプチャ中に行われていることを前提としています。 (私は実際にもっと多くをキャプチャしていますが、これは単なるサンプルの例です)

クロージャはどこに作成されていますか? 私はそれを制御できますか?または、パラメータを取る方法でマネージャを更新すると、

slot_data_to_copy dat; 

memory_manager::create_slot<slot_data_to_copy> 
     (100, dat, [](slot& sx, slot_data_to_copy& dat) 
      { sx.assign_data(dat); } 
     ); 

は全くスローされないことが保証されていますか?

WindowsでVisual C++を使用し、LinuxでGCCを使用してコンパイルしていますが、この動作はWindowsでのみ発生します(Linuxでは、おそらくどこかでメモリが不足します)。

EDIT:

http://en.cppreference.com/w/cpp/utility/functional/function/function - のstd ::機能は、オペレータnothrow含まれている..私はおそらく何かが欠けているんだけど、この(ラムダ)の状況で使用されている1?

+0

'変数のキャプチャ中にスローが行われたと仮定します。 ' - ラムダがヒープ上にコピーされていますか?それはいつリリースされるのですか? – nothrow

+1

[expr.prim。ラムダ式の評価結果は一時的にprvalueになります。この一時的なものは* closureオブジェクト*と呼ばれます。ここで使われている 'std :: function'のctorは' template以外の 'noexcept'である' template < class F > function(F f); 'です。 – dyp

答えて

4

クロージャはどこに作成されますか?

ラムダ式は、通常のファンクタクラスである名前のない型のオブジェクトを作成します。キャプチャされた変数は、その名前のない型のメンバです。

閉鎖が作成され
slot_data_to_copy dat; 

struct unnamed_lambda_type { 
    slot_data_to_copy &dat; 

    unnamed_lambda_type(slot_data_to_copy &dat_) : dat(dat_) {} 

    void operator() (slot &sx) const { 
    sx.assign_data(dat); 
    } 
}; 

memory_manager::create_slot(100, unnamed_lambda_type(dat)); 

あなたのコードmemory_manager::create_slot(100, [&dat](slot& sx) { sx.assign_data(dat); });は、本質的に同じですか?

クロージャオブジェクトは、通常はスタックに割り当てられた他の一時オブジェクトと同様です。

1

閉鎖は、です。キャプチャされた変数は、匿名の構造体のデータメンバーです(これがラムダです)。ラムダを作成すると、bad_allocを投げることはできません。あなたのエラーは他の場所です(おそらくstd::functionを作成しています。これはラムダをヒープにコピーしている可能性があります)。

サイドノート:あなたはラムダの参照によってキャプチャしています。ラムダが呼び出されるまでにslot_data_to_copy datが破壊されていないことを確認してください。値でコピーするか、ラムダをすぐに呼び出す必要があります。

+0

さて、私はスローが変数のキャプチャ中に行われたと仮定しました(std :: function <>の作成では、気にしません)。スタック上にstd :: functionを作成したいのですが、可能でしょうか? – nothrow

+0

'std :: function'はパラメータとして渡されているので、すでにスタックに入っています。 'std :: function'は内部的にヒープ上のラムダへのポインタを持っています(' std :: vector'がどのようにスタック上にあるかもしれないが、そのデータはヒープ上にあります)。 – Simple

+0

ad sidenote - 関数create_slotはラムダをどこにも保持しないので、データを破棄することはできません。 – nothrow

関連する問題