Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where are the closure's captured variables stored?

Tags:

c++

c++11

lambda

I'm working on memory intensive application, that should handle out-of-memory situations properly.

I have something like

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&)>); ........
}

This class handles, logs, and so on all of the out-of-memory issues, keeps ownership of all of the slots, and drives concurrency.

However, I have unhandled std::bad_alloc on following code:

slot_data_to_copy dat;

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

I assume that the throw is done during capturing the variables. (I'm capturing actually more of them, this is just a sample example)

Where is the closure created? Can I control it? Or, if I update the manager in a way that it takes parameter, like

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); }
       );

is it guaranteed that it doesn't throw at all?

I'm compiling both using Visual C++ on Windows and GCC on Linux, but I observed this behavior only on Windows (on linux, I run out of memory probably somewhere where I can handle it).

EDIT:

http://en.cppreference.com/w/cpp/utility/functional/function/function - std::function contains nothrow operators.. I'm probably missing something, but which one is used in this (lambda) situation?

like image 747
nothrow Avatar asked Oct 09 '13 18:10

nothrow


1 Answers

Where is the closure created?

A lambda expression creates an object of of an unnamed type that is just a normal functor class. The captured variables are members of that unnamed type.

Your code memory_manager::create_slot(100, [&dat](slot& sx) { sx.assign_data(dat); }); is essentially the same as:

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) );

Where is the closure created?

The closure object is just like any other temporary object, generally allocated on the stack.

like image 160
bames53 Avatar answered Sep 25 '22 16:09

bames53