C ++ 11 std :: Thread und virtuelle Funktion Bindung

9

Ich habe ein merkwürdiges C ++ - Code-Verhalten festgestellt, nicht sicher, ob es sich um einen Compiler-Fehler oder einfach um nicht definiertes / nicht spezifiziertes Verhalten meines Codes handelt. Hier ist der Code:

%Vor%

Die Ausgabe des Codes wäre die folgende, was nicht überraschend ist:

%Vor%

Wenn jedoch der Funktionsaufruf "sleep (1)" auskommentiert wird, lautet die Ausgabe:

%Vor%

Getestet unter Ubuntu 15.04 zeigen sowohl gcc-4.9.2 als auch clang-3.6.0 das gleiche Verhalten. Compiler-Optionen:

%Vor%

Es sieht nach einer Wettlaufsituation aus (die vtable ist nicht vollständig aufgebaut, bevor der Thread gestartet wird). Ist dieser Code schlecht formuliert? ein Compilerfehler? oder soll es so sein?

    
user416983 16.10.2015, 13:40
quelle

2 Antworten

4

@KerrekSB kommentierte:

  

" Der Thread verwendet das untergeordnete Objekt, aber das untergeordnete Objekt wird vor dem Verbinden des Threads zerstört (weil die Verknüpfung erst erfolgt, nachdem die Zerstörung des untergeordneten Objekts begonnen hat).

Das Objekt Child wird am Ende von main zerstört. Der Child destructor wird ausgeführt und ruft den Parent destructor auf, wobei Parent base (no so) und Datenelemente (das Thread-Objekt) zerstört werden. Da Destruktoren in der Kette von Basisklassen aufgerufen werden, ändert sich der dynamische Typ des Objekts in umgekehrter Reihenfolge, wie er sich während der Konstruktion ändert. An diesem Punkt lautet der Typ des Objekts Parent .

Die virtuellen Aufrufe in der Thread-Funktion können vor, nach oder nach dem Aufruf von Child destructor auftreten, und im Fall von Überlappungen gibt es einen Thread, der auf den Speicher (in der Praxis den vtable-Zeiger) zugreift, der geändert wird von einem anderen Thread. Das ist also Undefined Behavior.

    
Cheers and hth. - Alf 16.10.2015, 15:06
quelle
-1

Dies ist ein häufiges Designproblem. Was Sie versucht haben, ist ein klassisches Anti-Muster.

Parent kann nicht gleichzeitig ein Thread-Manager sein, einen Thread starten und auf Thread-Beendigung warten:

%Vor%

und auch ein Thread-Objekt:

%Vor%

Dies sind zwei verschiedene Konzepte mit streng inkompatiblen Spezifikationen.

(Und Thread-Objekte sind im Allgemeinen nicht nützlich.)

    
curiousguy 28.10.2015 13:53
quelle