Pimpl + QSharedPointer - Destruktor = Katastrophe

8

Gestern bin ich in Elend gestürzt, was mich 24 Stunden frustriert hat. Das Problem ist auf unerwartete Abstürze auf random Basis zurückzuführen. Um die Dinge zu komplizieren, hatten die Debug-Berichte auch ein absolut zufälliges -Muster. Um es noch komplizierter zu machen, führten alle Debugging-Traces entweder zu zufälligen Qt-Quellen oder zu nativen DLLs, d. H., Jedes Mal, wenn das Problem nicht auf meiner Seite ist.

Hier sind ein paar Beispiele für solche schönen Berichte:

%Vor% %Vor% %Vor%

Wie Sie sehen können, ist dieses Zeug ziemlich eklig, es gibt keine sinnvollen Informationen. Aber da war eine Sache, auf die ich nicht geachtet habe. Es war eine seltsame Warnung während der Kompilation, die auch schwer zu verstehen ist:

%Vor%

Eigentlich habe ich diese Warnung nur als letzten Ausweg betrachtet, weil bei einer so verzweifelten Suche nach einem Bug der Code bereits wörtlich mit dem Holzeinschlag infiziert war.

Nachdem ich es sorgfältig gelesen hatte, erinnerte ich mich daran, dass man zum Beispiel, wenn man std::unique_ptr oder std::scoped_ptr für Pimpl verwendet, Desctructor bereitstellen sollte, sonst wird der Code nicht einmal kompiliert. Ich erinnere mich aber auch daran, dass std::shared_ptr sich nicht um Destruktoren kümmert und ohne sie funktioniert. Es war ein weiterer Grund, warum ich diese seltsame Warnung nicht beachtet habe. Lange Rede, kurzer Sinn, als ich Destruktor hinzugefügt habe, hat dieser zufällige Absturz aufgehört. Sieht so aus, als hätte Qt's QSharedPointer einige Designfehler im Vergleich zu std::shared_ptr . Ich denke, es wäre besser, wenn Qt-Entwickler diese Warnung in Fehler umwandeln würden, weil Debugging-Marathons einfach nicht die Zeit, Mühe und Nerven .

Meine Fragen sind:

  1. Was stimmt nicht mit QSharedPointer ? Warum Destruktor ist so wichtig?
  2. Warum ist der Absturz passiert, als es keinen Destruktor gab? Diese Objekte (die Pimpl + QSharedPointer verwenden) werden auf dem Stapel erstellt, und nach ihrem Tod haben keine anderen Objekte mehr Zugriff darauf. Ein Absturz geschah jedoch während eines zufälligen Zeitraums nach ihrem Tod.
  3. Ist schon mal jemand auf solche Probleme gestoßen? Bitte teilen Sie Ihre Erfahrung.
  4. Gibt es andere Fallstricke? wie das in Qt - die ich muss sicher wissen, um zu bleiben sicher in der Zukunft?

Hoffentlich werden diese Fragen und mein Beitrag im Allgemeinen anderen helfen, die Hölle zu vermeiden, in der ich die letzten 24 Stunden gewesen bin.

    
Alexander Shukaev 15.03.2013, 20:52
quelle

2 Antworten

3

Das Problem wurde in Qt 5 behoben, siehe Ссылка

Der Compiler, der den falschen Destruktor aufruft oder ein anderes Speicherlayout annimmt, führt wahrscheinlich zu einer Art von Speicherbeschädigung. Ich würde sagen, dass ein Compiler für dieses Problem einen Fehler und keine Warnung geben sollte.

    
capisce 18.03.2013, 07:31
quelle
1

Sie werden auf ein ähnliches Problem mit std::unique_ptr stoßen, was auch zu kaputten Destruktoren führen kann, wenn sie mit einem unvollständigen Typ verwendet werden. Der Fix ist natürlich ziemlich trivial - ich deklariere einen Konstruktor für die Klasse und definiere ihn dann in der Implementierungsdatei als

%Vor%

Der Grund dafür, dass dies ein Problem für std::unique_ptr , aber nicht für std::shared_ptr ist, ist, dass der Destruktor Teil des ersten Typs ist, aber ein Mitglied des Letzteren ist.

    
Toby Speight 03.11.2015 13:54
quelle