2016-05-07 5 views
3

Ich habe folgenden Code-Block, was ich erwartet, ist die i innerhalb der Lambda-Capture-Liste wird durch Wert übergeben und die i ausgegeben werden sollte anders sein. Das tatsächliche Ergebnis ist der Ausgang 20 Zeilen von 19 is completed.Warum hat diese Lambda-Funktion in der Schleife den Parameter nicht als Wert erfasst?

Ich habe versucht, diese Zeile std::thread t([&func](){ zu std::thread t([func](){ zu ändern, der Ausgang könnte verschiedene i Wert drucken.

Meine Frage ist, warum std::thread t([&func](){ und std::thread t([func](){ die verschiedenen Ausgabewerte von i führen?

void DoSomething(std::function<void()> func) 
{ 
    std::thread t([&func](){ 
     //do something 
     sleep(1); 
     if (func) 
      func(); 
    }); 
    t.detach(); 
} 

int main(int argc, const char * argv[]) { 
    std::mutex mtx; 
    for (int i = 1 ; i < 20; i ++) { 
     DoSomething([i, &mtx](){ 
      std::unique_lock<std::mutex> lock(mtx); 
      std::cout << i << " is completed" << std::endl;; 
     }); 
    } 
    sleep(10); 
} 

Antwort

2

Sie erfassen einen Verweis auf DoSomething ‚s-Parameter, func.
Zu dem Zeitpunkt, zu dem Ihr Thread ausgeführt wird, ist die Lebensdauer dieses Parameters beendet, so dass Sie eine freie Referenz haben und diese nicht definiert ist.

+0

bedeutet das, dass die an die DoSomething übergebene Funktion die Informationen über die Erfassungsliste enthält? – 2power10

+0

@ 2power10 Ich bin mir nicht sicher, was Sie fragen. Wenn Sie über Referenz erfassen, müssen Sie sicherstellen, dass das referenzierte Objekt gültig ist, wenn Sie es verwenden, andernfalls ist das Programm nicht definiert. Wertvolle Erfassung ist hier richtig. – molbdnilo

0

Das Thread-Objekt t in DoSomething() empfängt einen Verweis auf das Objekt func, das als Wert übergeben wird. Wenn func() ausgeführt wird, wartet es möglicherweise auf mutex durch den Aufruf std::unique_lock<std::mutex> lock(mtx); In der Zwischenzeit wird t.detach() aufgerufen und die Funktion würde durch das Zerstören des by-Wert-Parameters func beendet werden. Dies führt zu einer baumelnden Referenz wie von @ molbidnilo gesagt.

Das Problem kann durch den Aufruf t.join(); anstelle von t.detach() gelöst werden.

+0

Verwenden Sie 't.join()' wird 'DoSomething' blockieren, und deshalb verwende ich' t. detach() 'hier. Ich denke, dass das Problem gelöst werden kann, indem man die Funktion nach Wert anstatt nach Referenz erfasst. – 2power10

0

Wenn Sie t.detach() verwenden, wird der Thread unabhängig ausgeführt, jetzt übergeben Sie das Funktionsobjekt per Verweis. Wenn also das Funktionsobjekt zerstört wurde, während der unabhängige Thread versucht, einen Verweis zu erstellen, würde dies nicht zum Absturz führen des Programms. , aber wenn Sie das Funktionsobjekt nach Wert übergeben, ist dieses Problem gelöst. Ich habe Ihren Code in meinem Computer getestet. Er ist abgestürzt, wenn das Funktionsobjekt per Referenz übergeben wurde.

Verwandte Themen