Ist hier UB zu erkennen?
-
Und was ist der Bug?
-
nwp3 schrieb:
Ich sehe keinen Fehler, aber ich würde ein paar asserts einbauen:
void execute(){ assert(this); assert(this->doActualWork); assert(unfinishedTasks); assert(started); //vielleicht nicht wichtig this->doActualWork(); unfinishedTasks--; }Vielleicht wird ein Pointer falsch gecastet und deswegen greift this->doActualWork daneben. Das könnte den Unterschied bei Release und Debug erklären.
Ich vermute eher nen Compiler-Bug. Wenn ich die Klasse dupliziere (namen ändere, extra dateien dafür, etc.) und dann in nem minimalen Beispiel verwende, existiert der Bug nicht. Wenn ich im gleichen minimalen Beispiel die originale Task Klasse verwende, tritt der Bug auch auf. Lustigerweise: Wenn ich dann im normalen Code (also nicht minimalbeispiel), die Verwendung von der Task Klasse auf die duplizierte Klasse umstelle, tritt der Bug auch auf - auch im minimalen Beispiel. Und ebenso tritt der Bug mit der originalklasse im Minimalbeispiel (im "Haupt-Code" schon) nicht auf, wenn ich im nicht-minimal-beispiel-code die duplizierte Klasse, und im Minimalbeispielcode die originale Klasse verwende.
D.h. in der Benutzung außerhalb des minimalen Beispiels der Task Klasse muss irgendwas passieren, dass dem Compiler sagt: Das hier kannst du wegoptimieren, und dann krachts irgendwo. Das ist aber aufgrund der Natur des Bugs noch verwirrender, weil in der auslösenden Stelle nur Zeiger rumgeschoben werden. Konkret:
manni66 schrieb:
Und was ist der Bug?
Wenn dich Details wirklich interessieren (sollte für das Beispiel aber nicht relevant sein): http://stackoverflow.com/questions/18550883/cds-library-michael-deque-causes-crash-when-pushing-back-derived-type-of-custom
Im Prinzip mach ich ein push_back in einen Container von irgendeiner library (nicht STL), wobei der Container aber nur einen Zeiger auf Task* als Typ T hat und ich einen Zeiger auf einen abgeleiteten typen push_back()en will. Und da gibts nen Crash. Konkret stell ich fest, dass der Bug da auftritt, weil ich direkt davor und direkt danach ein cout<<"hallo"<<std::endl; mache und nur das cout vor dem push_back() ankommt bevor der Crash passiert.
-
verschwindet der Fehler, wenn du aus dem std::atomic irgendwas anderes machst?
-
otze schrieb:
verschwindet der Fehler, wenn du aus dem std::atomic irgendwas anderes machst?
Nö, leider nicht.
edit: aha, jetzt da du std::atomic erwähnst... ich hab das ganze Projekt noch mal neu kompiliert, und eine neue Warnung entdeckt. Anscheinend modifiziert ne Template-Spezialisierung für 64 bit unsigned ints in xatomic.h (ein VS2012-Header) ebp ohne vorher ein backup auf den Stack zu schieben und danach wieder zu poppen. Ich glaub die verwendete Bibliothek benutzt ein atomic des Typs, bei dem das gemacht wird, was den Crash verursachen könnte. Muss mal bisschen nachforschen, brb.
-
Tatsächlich! Hab die Bibliothek mal so umgeschrieben, dass sie andere atomics als die aus std verwendet, und der Bug ist verschwunden.
-
You are welcome.
-
Sone schrieb:
virtual ~Task() = 0 {};Ok, das kann nur Pseudo-Code sein...

Wieso das?
-
Tachyon schrieb:
Sone schrieb:
virtual ~Task() = 0 {};Ok, das kann nur Pseudo-Code sein...

Wieso das?
Weil das kein gültiges Standard-C++ ist. Oder es ist eine Implementations-Erweiterung von VC++...
§10.4/2 schrieb:
A function declaration cannot provide both a pure-specifier and a definition
-
Tachyon schrieb:
Sone schrieb:
virtual ~Task() = 0 {};Ok, das kann nur Pseudo-Code sein...

Wieso das?
Man kann pure virtual functions nur außerhalb der Klassendefinition definieren.
-
Nathan schrieb:
Man kann pure virtual functions nur außerhalb der Klassendefinition definieren.
Das weiß er doch - würde mich schwer wundern wenn nicht.
-
Sone schrieb:
Nathan schrieb:
Man kann pure virtual functions nur außerhalb der Klassendefinition definieren.
Das weiß er doch - würde mich schwer wundern wenn nicht.
Tachyon fragte, wieso das nur Pseudocode sein kann, ich gab einen Grund.
Wieso meinst du, dass er das dann schon weiß, wenn er doch fragt?
Du hast ihm doch auch geantwortet.
-
Was den Körper von Destruktoren von abstrakten Klassen angeht: Ist erlaubt. Hier ( http://stackoverflow.com/questions/1219607/why-do-we-need-a-pure-virtual-destructor-in-c ) wird sogar behauptet, dass pur virtuelle Destruktoren eine Implementierung benötigen, aber ich hab keinen Standard auf der Festplatte und bei Google finde ich keine Quellen.
-
Nathan schrieb:
Sone schrieb:
Nathan schrieb:
Man kann pure virtual functions nur außerhalb der Klassendefinition definieren.
Das weiß er doch - würde mich schwer wundern wenn nicht.
Tachyon fragte, wieso das nur Pseudocode sein kann, ich gab einen Grund.
Wieso meinst du, dass er das dann schon weiß, wenn er doch fragt?
Du hast ihm doch auch geantwortet.Stimmt, tut mir Leid. Tachyon sollte das aber wissen, der Kerl ist schon viel länger dabei als ich oder du.
Was den Körper von Destruktoren von abstrakten Klassen angeht: Ist erlaubt.
Klar, aber nicht bei der Deklaration. Dass sie definiert werden müssen ist klar.
-
Sone schrieb:
Nathan schrieb:
Sone schrieb:
Nathan schrieb:
Man kann pure virtual functions nur außerhalb der Klassendefinition definieren.
Das weiß er doch - würde mich schwer wundern wenn nicht.
Tachyon fragte, wieso das nur Pseudocode sein kann, ich gab einen Grund.
Wieso meinst du, dass er das dann schon weiß, wenn er doch fragt?
Du hast ihm doch auch geantwortet.Stimmt, tut mir Leid. Tachyon sollte das aber wissen, der Kerl ist schon viel länger dabei als ich oder du.
Was den Körper von Destruktoren von abstrakten Klassen angeht: Ist erlaubt.
Klar, aber nicht bei der Deklaration. Dass sie definiert werden müssen ist klar.
Achso, dann hab ich falsch verstanden worum es geht, sorry

-
Sone schrieb:
[[...]Tachyon sollte das aber wissen, der Kerl ist schon viel länger dabei als ich oder du.[...]
Ach ja, da war was. Ich habe schlicht die Definition überlesen...