Home > Mobile >  terminate called without an active exception Aborted
terminate called without an active exception Aborted

Time:05-06

#include <iostream>
#include <vector>
#include <algorithm>
#include <thread>
#include <functional>
#include <utility>
#include <unistd.h>

using namespace std;

class Track{
public:
    Track(int t) : m_track(t){}
    int GetTrack() { return m_track; }
    void SetTrack(int track) { m_track = track; }
private:
    int m_track;
};

class Observer{
public:
    Observer(Track track) : m_track(track) { }
    virtual void run() = 0;
    virtual ~Observer(){
        cout << "Observer Destructor" << endl;
    }
protected:
    Track m_track;
    double running = 0;
};

class Rabbit : public Observer{
public:
    Rabbit(Track track) : Observer(track) { }
    void run(){
        while(running <= m_track.GetTrack()){
            running  = 10;
            cout << "rabbit run " << running << endl;
            sleep(1);
            if(running == m_track.GetTrack() / 3 * 2){
                sleep(62);
            }
        }
        cout << "Rabbit win" << endl;
        //End another thread(Turtle thread);
    }
    ~Rabbit() = default;
};

class Turtle : public Observer{
public:
    Turtle(Track track) : Observer(track) { }
    void run(){
        while(running <= m_track.GetTrack()){
            running  = 10.0 / 3;
            cout << "turtle run " << running << endl;
            sleep(1);
        }
        cout << "Turtle win" << endl;
        //End another thread(Rabbit thread);
    }
    ~Turtle() = default;
};

class Judge{
public:
    Judge(Track track) : m_track(track) { }
    void add(Observer* observer){
        observers.push_back(observer);  
    }

    void remove(Observer* observer){
        auto temp = find(observers.begin(), observers.end(), observer);
        if(temp != observers.end()){
            observers.erase(temp);
        }
    }

    void notify(){
        for(int i = 0; i != observers.size(); i  ){
            //Start the thread to execute the run function of the subclass
            thread t([&](){
                observers[i]->run();
            });
            threads.push_back(&t);
        }
        for(int i = 0; i != observers.size(); i  ){
            if(threads[i]->joinable())
                threads[i]->join();
        }
    }

    ~Judge() = default;

private:
    vector<Observer*> observers;
    Track m_track;
    vector<thread*> threads;
};

int main(){
    Track track(300);
    Observer* rabbit = new Rabbit(track);
    Observer* turtle = new Turtle(track);
    Judge* judge = new Judge(track);
    judge->add(rabbit);
    judge->add(turtle);
    judge->notify();
    delete rabbit;
    delete turtle;
    delete judge;
    return 0;
}

I want to use the observer pattern, and call the notify function in the Judge class to notify the two subclasses to start the run function by thread, but i reported this error

terminate called without an active exception
Aborted

How to fix this problem and add features in two subclass. What this program solves is, suppose the track is 300 meters long, the speed of the tortoise is 10/3 m/s, the speed of the rabbit is 10 m/s, the tortoise keeps running, and the hare runs 2/3 of the way to the At 200 meters, after resting for 62 seconds, the tortoise won the race. try (1) Write a program to simulate the process and results of the tortoise and the hare race according to the realization principle of the observer mode

CodePudding user response:

Two issues in one place:

for(int i = 0; i != observers.size(); i  ){
            //Start the thread to execute the run function of the subclass
            thread t([&](){
                observers[i]->run();
            });
            threads.push_back(&t);
        }

The pointer you store in the vector becomes a dangling pointer right after you pushed it to the vector, because the thread t goes out of scope and gets destroyed. The destructor of std::thread terminates when you didn't join the thread.

Use a std::vector<std::thread> and make sure the threads are alive as long as you want to use them and dont get destroyed before you join them.

Perhaps you used pointers because std::thread cannot be copied, but it can be moved.

CodePudding user response:

The problem is with this line:

threads.push_back(&t);

It pushes the pointer of a std::thread object to a vector, but the std::thread object goes out of scope directly after that. So, the std::thread object gets destroyed and leaves a dangling pointer in the std::vector.

Change the vector to hold the std::thread objects directly and use

threads.push_back(std::move(t));

to push the objects into the vector.

Also the threads variable does not have to be a member variable. It is enough to be a local variable in the notify function.

Full program: https://godbolt.org/z/bTWs9f69E

You can also use emplace_back to create the thread object in the vector directly and use ranged based for loops.

void notify(){
    vector<thread> threads;
    for(auto &observer : observers){
        //Start the thread to execute the run function of the subclass
        
        threads.emplace_back(thread([&observer](){
            observer->run();
        }));
    }
    for(auto &t : threads){
        if(t.joinable())
            t.join();
    }
}
  • Related