Gibt es eine Möglichkeit zu erkennen, ob eine Klasse mit nicht-virtuellem Basisdestruktor falsch gelöscht wird?

8

Das sehr bekannte Szenario:

%Vor%

Außerdem kann nicht einmal Valgrind einen solchen Fehler finden, vorausgesetzt, dass die Größe von A und B gleich ist.

Gibt es ein Tool, das solche Fehler zumindest für einen Debug-Build oder ein Idiom, das solche Fehler für eine bestimmte Klasse erkennt, finden könnte?

    
Martin Drozdik 27.03.2016, 15:10
quelle

2 Antworten

5

Für gcc können Sie Folgendes angeben:

%Vor%

um delete-non-virtual-dtor warning generiert by std::default_delete zu sehen, wird es wie folgt aussehen:

  

/ usr / local / include / c ++ / 5.3.0 / bits / unique_ptr.h: 76: 2: Warnung: das Löschen von Objekten des polymorphen Klassentyps 'B' mit nicht virtuellem Destruktor kann zu undefiniertem Verhalten führen [-Welete -nicht-virtuell-dtor]     Löschen Sie __ptr;

live

übrigens. Ihren Beispielklassen fehlt mindestens eine virtuelle Funktion in der Basisklasse.

[Bearbeiten]

um es in Fehler umzuwandeln, benutze:

%Vor%     
marcinj 27.03.2016, 15:20
quelle
1

Ich bin der festen Überzeugung, dass man "wertbasierte" Klassen und "OO-basierte" Klassen (aus Mangel an besserem Begriff) streng trennen sollte.

Wertbasierte Klassen sollten keine öffentlichen Basen haben und normalerweise die Kopiersemantik unterstützen (es sei denn, sie sind speziell darauf ausgelegt, das Kopieren zu deaktivieren). Objekte solcher Klassen haben keine Identitäten außer ihren Werten. Sie sind mit ihren Kopien austauschbar.

OO-basierte Klassen sollten virtuelle Destruktoren haben und sollten niemals Kopierelemente öffentlich zugänglich machen. Objekte solcher Klassen sollten nur über eine virtuelle Methode clone kopiert werden. Solche Objekte haben Identitäten, die von ihren Werten getrennt sind.

Es sollte keine Klasse mit einer öffentlichen Basis geben, die einen nicht virtuellen Destruktor oder einen öffentlichen copy / move ctor oder einen öffentlichen Kopier- / Verschiebezuweisungsoperator (in der Basis) hat.

Wenn Sie diese Trennung beibehalten, haben Sie keine Unfälle mit Objekt-Slicing oder Deletion durch einen nicht-polymorphen Basiszeiger.

Leider gibt es keine Werkzeuge (von denen ich weiß), die helfen, diese Trennung aufrechtzuerhalten. Sie müssen also beim Erben die gebotene Sorgfalt walten lassen. Es ist wirklich einfach. Gibt es eine virtuelle dtor und unzugängliche / gelöschte Kopie ctor und Kopierzuweisung? Sie können öffentlich erben. Nein? Vermeide potentielle Unordnung, verwende Komposition oder private Vererbung.

Eine gute Klasse, die für die Vererbung entworfen wurde, würde ihre kopierenden Mitglieder geschützt haben, um das Klonen in absteigenden Klassen zu erleichtern.

Leider haben Sie bei Klassen von Drittanbietern keine Wahl, da die Autoren die kopierenden Mitglieder normalerweise veröffentlichen, so dass immer noch das Risiko besteht, dass Objekte zerschnitten werden. Aber Sie haben kein Risiko eines unpassenden Löschens durch einen Basiszeiger.

TL; DR keine Werkzeuge, nur Due Diligence des Programmierers.

    
n.m. 27.03.2016 19:45
quelle

Tags und Links