C++-beëindiging aangeroepen zonder een actieve uitzondering

Ik krijg een C++-fout bij threading:

terminate called without an active exception
Aborted

Hier is de code:

#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
template<typename TYPE>
class blocking_stream
{
public:
    blocking_stream(size_t max_buffer_size_)
        :   max_buffer_size(max_buffer_size_)   
    {
    }
    //PUSH data into the buffer
    blocking_stream &operator<<(TYPE &other)
    {
        std::unique_lock<std::mutex> mtx_lock(mtx); 
        while(buffer.size()>=max_buffer_size)
            stop_if_full.wait(mtx_lock);
        buffer.push(std::move(other));
        mtx_lock.unlock();
        stop_if_empty.notify_one();
        return *this;
    }
    //POP data out of the buffer 
    blocking_stream &operator>>(TYPE &other)
    {
        std::unique_lock<std::mutex> mtx_lock(mtx);
        while(buffer.empty())
            stop_if_empty.wait(mtx_lock);
        other.swap(buffer.front()); 
        buffer.pop();
        mtx_lock.unlock();
        stop_if_full.notify_one();
        return *this;
    }
private:
    size_t max_buffer_size;
    std::queue<TYPE> buffer;
    std::mutex mtx;
    std::condition_variable stop_if_empty,
                            stop_if_full;
    bool eof;   
};

Ik heb mijn code gemodelleerd rond dit voorbeeld:
http://www.justsoftwaresolutions.co.uk/ threading/implementatie-a-thread-safe-queue-using-condition-variables.html

Wat doe ik verkeerd en hoe los ik de fout op?


Antwoord 1, autoriteit 100%

Als een thread-object buiten het bereik valt en het in de status van koppelbaar is, wordt het programma beëindigd. De Standaardcommissie had twee andere opties voor de vernietiger van een koppelbare draad. Het zou stilletjes kunnen toetreden — maar het zou kunnen dat join nooit meer terugkomt als de draad vastzit. Of het kan de draad losmaken (een losgemaakte draad is niet koppelbaar). Losgemaakte threads zijn echter erg lastig, omdat ze tot het einde van het programma kunnen overleven en de vrijgave van bronnen kunnen verknoeien. Dus als je je programma niet wilt beëindigen, zorg er dan voor dat je aan elke thread deelneemt (of loskoppelt).


Antwoord 2, autoriteit 35%

Hoe kan ik die fout reproduceren:

#include <iostream>
#include <stdlib.h>
#include <string>
#include <thread>
using namespace std;
void task1(std::string msg){
  cout << "task1 says: " << msg;
}
int main() { 
  std::thread t1(task1, "hello"); 
  return 0;
}

Compileren en uitvoeren:

el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11
el@defiant ~/foo4/39_threading $ ./s
terminate called without an active exception
Aborted (core dumped)

Je krijgt die foutmelding omdat je je thread niet hebt toegevoegd of losgekoppeld.

Een manier om het op te lossen, sluit je als volgt aan bij de thread:

#include <iostream>
#include <stdlib.h>
#include <string>
#include <thread>
using namespace std;
void task1(std::string msg){
  cout << "task1 says: " << msg;
}
int main() { 
  std::thread t1(task1, "hello"); 
  t1.join();
  return 0;
}

Vervolgens compileren en uitvoeren:

el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11
el@defiant ~/foo4/39_threading $ ./s
task1 says: hello

De andere manier om het te repareren, maakt het als volgt los:

#include <iostream>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include <thread>
using namespace std;
void task1(std::string msg){
  cout << "task1 says: " << msg;
}
int main() 
{ 
     {
        std::thread t1(task1, "hello"); 
        t1.detach();
     } //thread handle is destroyed here, as goes out of scope!
     usleep(1000000); //wait so that hello can be printed.
}

Compileren en uitvoeren:

el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11
el@defiant ~/foo4/39_threading $ ./s
task1 says: hello

Lees meer over het loskoppelen van C++-threads en het samenvoegen van C++-threads.


Antwoord 3, autoriteit 14%

Eric Leschinski en Bartosz Milewski hebben het antwoord al gegeven. Hier zal ik proberen het op een meer beginnersvriendelijke manier te presenteren.

Als een thread eenmaal is gestart binnen een scope (die zelf op een thread draait), moet men er expliciet voor zorgen dat een van de volgende dingen gebeurt voordat de thread buiten het bereik gaat:

  • De runtime verlaat het bereik, pas nadat die thread is uitgevoerd. Dit wordt bereikt door mee te doen met die draad. Let op de taal, het is de buitenste reikwijdte die aansluit bij die draad.
  • De runtime laat de thread op zichzelf lopen. Het programma zal dus de scope verlaten, of deze thread nu klaar is met uitvoeren of niet. Deze thread wordt vanzelf uitgevoerd en afgesloten. Dit wordt bereikt door de draad los te maken. Dit kan tot problemen leiden, bijvoorbeeld als de thread verwijst naar variabelen in dat buitenste bereik.

Let op, tegen de tijd dat de thread wordt samengevoegd of losgekoppeld, is het mogelijk dat deze al goed is uitgevoerd. Toch moet een van de twee bewerkingen expliciet worden uitgevoerd.


Antwoord 4

jaar, de thread moet join() zijn. wanneer de hoofduitgang


Antwoord 5

Zolang je programma doodgaat, en dan zonder loskoppelen of samenvoegen van de draad, zal deze fout optreden. Zonder de draad los te maken en samen te voegen, zou u een eindeloze lus moeten geven na het maken van de draad.

int main(){
std::thread t(thread,1);
while(1){}
//t.detach();
return 0;}

Het is ook interessant dat de draad na het slapen of lussen kan worden losgemaakt of samengevoegd. Ook op deze manier krijg je deze foutmelding niet.

Het onderstaande voorbeeld laat ook zien dat de derde thread zijn werk niet kan doen voordat de hoofddobbelsteen. Maar deze fout kan ook niet optreden, zolang je maar ergens in de code loskoppelt.
Derde draad slaapt 8 seconden, maar hoofd gaat over 5 seconden dood.

void thread(int n) {std::this_thread::sleep_for (std::chrono::seconds(n));}
int main() {
std::cout << "Start main\n";
std::thread t(thread,1);
std::thread t2(thread,3);
std::thread t3(thread,8);
sleep(5);
t.detach();
t2.detach();
t3.detach();
return 0;}

Antwoord 6

Eerst definieert u een thread. En als je nooit join() of detach() aanroept voordat je de thread destructor aanroept, wordt het programma afgebroken.

Als volgt, is het aanroepen van een thread-destructor zonder eerst join (wachten tot het klaar is) of detach aan te roepen gegarandeerd om onmiddellijk std::terminate aan te roepen en het programma te beëindigen.

Het impliciet ontkoppelen of samenvoegen van een joinable() thread in zijn
destructor kan resulteren in moeilijk te debuggen correctheid (voor loskoppelen)
of prestatie (voor deelname) bugs die alleen worden aangetroffen wanneer een uitzondering is
verhoogd. De programmeur moet er dus voor zorgen dat de destructor nooit
uitgevoerd terwijl de thread nog kan worden samengevoegd.

Other episodes