2013-10-09 16 views
5

Sto lavorando a un'applicazione che richiede molta memoria, che dovrebbe gestire correttamente le situazioni di esaurimento della memoria.Dove vengono memorizzate le variabili catturate dalla chiusura?

ho qualcosa di simile

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

gestisce Questa classe, tronchi, e così via tutti i problemi out-of-memory, mantiene la proprietà di tutti gli slot e le unità concorrenza.

Tuttavia, ho non gestita std::bad_alloc il seguente codice:

slot_data_to_copy dat; 

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

Si considera che il lancio è fatto durante la cattura delle variabili. (Sto catturando in realtà più di loro, questo è solo un esempio di esempio)

Dove viene creata la chiusura? Posso controllarlo? Oppure, se aggiorno il manager in un modo che ci vuole parametro, come

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

è garantito che non si butta a tutti?

Sto compilando entrambi utilizzando Visual C++ su Windows e GCC su Linux, ma ho osservato questo comportamento solo su Windows (su Linux, ho esaurito la memoria probabilmente da qualche parte dove posso gestirlo).

EDIT:

http://en.cppreference.com/w/cpp/utility/functional/function/function - std :: funzione contiene nothrow operatori .. Sto probabilmente manca qualcosa, ma quale è usato in questo (lambda) situazione?

+0

'Suppongo che il lancio venga eseguito durante l'acquisizione delle variabili. '- il lambda viene copiato sull'heap? e quando viene rilasciato? – nothrow

+1

[expr.prim.lambda]/2 "La valutazione di un'espressione lambda si traduce in un valore provvisorio. Questo temporaneo è chiamato * oggetto di chiusura *." Il ctor di 'std :: function' che è usato qui è' template < class F > function (F f); ', che è * not *' noexcept'. – dyp

risposta

4

Dove viene creata la chiusura?

Un'espressione lambda crea un oggetto di un tipo senza nome che è solo una normale classe di functor. Le variabili catturate sono membri di quel tipo senza nome.

Il codice memory_manager::create_slot(100, [&dat](slot& sx) { sx.assign_data(dat); }); è essenzialmente la stessa:

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

Dove è la chiusura creato?

oggetto La chiusura è come qualsiasi altro oggetto temporaneo, generalmente allocato sullo stack.

1

La chiusura è la lambda; le variabili catturate sono membri di dati di una struttura anonima (questo è ciò che è un lambda). Creare il tuo lambda non può lanciare bad_alloc; il tuo errore è altrove (probabilmente creando lo std::function, che potrebbe copiare il lambda sull'heap).

Sidenote: stai catturando per riferimento nella tua lambda; assicurati che il tuo slot_data_to_copy dat non venga distrutto dal momento in cui viene chiamato il lambda. Dovresti copiarlo per valore o chiamare immediatamente il lambda.

+0

Ok, ho pensato che il lancio sia fatto durante l'acquisizione di variabili (se è fatto nella creazione di std :: function <>, non importa). Mi piacerebbe che la funzione std :: fosse creata in pila, sarebbe possibile? – nothrow

+0

Il 'std :: function' viene passato come parametro in modo che sia già in pila. 'std :: function' internamente ha un puntatore al lambda sull'heap (pensa a come' std :: vector' può essere nello stack ma i suoi dati sono nell'heap). – Simple

+0

sidenote annuncio - la funzione create_slot non mantiene il lambda ovunque, quindi i dati non possono essere distrutti. – nothrow

Problemi correlati