9 Stimmen

Verbinden einer boost::thread-Instanz im Destruktor

Ich sehe ein Problem, bei dem ein Aufruf von boost's thread->join in einem Destruktor zu einem Deadlock führt. Ich verstehe nicht, warum, und ich bin nicht allzu scharf darauf, Code, der einfach funktioniert (und ich verstehe nicht, warum es tut) in dem Projekt zu halten.

Klassendeklaration (ich habe der Kürze halber die run()-Methode von try/catch entfernt: laut der Boost-Thread-Dokumentation sollte das Ergebnis mit oder ohne sie dasselbe sein):

class B 
{
public:
    void operator()(){run();}
    void run();
    void shutdown();
    ~B();
    B();
    boost::thread *thr;
    bool shutdown_requested;
};

void B::shutdown()
{
    shutdown_requested = true;

    if (thr != NULL)
    {
        thr->interrupt();
        thr->join(); // deadlock occurs here!
        delete thr;
        thr = NULL;
    }
}

B::~B()
{
    shutdown();
}

B::B()
{
    thr = new boost::thread(boost::ref(*this));
}

void B::run()
{
    while (!shutdown_requested)
    {
        boost::xtime xt;
        boost::xtime_get(&xt, boost::TIME_UTC);
        xt.sec += 30;
        boost::this_thread::sleep(xt);
    }
}

Schnipsel, die nicht funktionieren:

int main()
{
    B *b = new B;

    Sleep(5000);
    printf("deleting \n");fflush(stdout);
//    b->shutdown();
    delete b;
    printf("done\n");fflush(stdout);

    return 0;
}

Ein Ausschnitt, der funktioniert:

int main()
{
    B *b = new B;

    Sleep(5000);
    printf("deleting \n");fflush(stdout);
    b->shutdown();
    delete b;
    printf("done\n");fflush(stdout);

    return 0;
}

Ich denke, der Grund für dieses Verhalten hat etwas mit diesem Ausschnitt aus der boost-Dokumentation zu tun:

muss der Benutzer von Boost.Thread sicherstellen dass das Objekt, auf das verwiesen wird, den den neu erstellten Ausführungsfaden überdauert.

Aber ich verstehe nicht wirklich, warum die Sackgasse - Beitritt der Thread würde nicht den Destruktor auf B und das Objekt selbst ist nicht gelöscht, wenn die run()-Methode zu beenden soll.

4voto

laura Punkte 7152

Ich habe das Problem gefunden: Es läuft auf einen übereifrigen Programmierer hinaus.

Ich hatte mein Projekt ursprünglich mit DUMA kompiliert ( http://sourceforge.net/projects/duma/ ), um zu sehen, ob meine Implementierung des aktuellen Moduls leckfrei ist. Leider waren in meiner Test-Sandbox auch die Duma-Einstellungen aktiviert, was mir erst auffiel, als ich den Code in einem Debugger durchging.

Nach dem Entfernen aller Speicherleck-Erkennungen funktioniert alles wie erwartet.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X