Is there a way to determine if a class was incorrectly deleted using a non-virtual database destructor?

The most famous scenario:

#include <memory> class A{}; class B : public A {}; int main() { std::unique_ptr<A> a = std::make_unique<B>(); // bam, when a gets deleted, we have undefined behavior. return 0; } 

Moreover, even Valgrind cannot catch such an error, provided that the sizes A and B coincide.

Is there any tool that could catch such errors, at least to build debugging, or some idiom that would detect such errors for a particular class?

+8
c ++
source share
2 answers

For gcc, you can specify:

 -Wdelete-non-virtual-dtor -Wsystem-headers 

to see the delete-non-virtual-dtor warning generated by std::default_delete , it will look like this:

/usr/local/include/++/5.3.0/bits/unique_ptr.h: 76: 2: warning: deleting an object of type polymorphic class "B" that has a non-virtual destructor may cause undefined -Wdelete-non-virtual behavior -dtor] remove __ptr;

live

by the way. your class samples do not have at least one virtual function in the base class.

[edit]

to turn it into using errors:

  -Werror=delete-non-virtual-dtor -Wsystem-headers 
+5
source share

I firmly believe that you need to strictly separate classes based on value and classes based on OO (due to the lack of a better term).

A value-based class should not have shared databases and should usually support copy semantics (unless specifically designed to disable copying). Objects of such classes have no identities except their meanings. They are interchangeable with their copies.

OO-based classes should have virtual destructors and should never publicly receive copies. Objects of such classes should only be copied using the virtual clone method. Such objects have identities separated from their meanings.

There should not be a class with a public base in which there is no virtual destructor or a public copy / move ctor or a public copy / move assignment operator (in the database).

If you keep this separation, you will not have any accidents with the splitting of objects or their removal using a non-polymorphic base pointer.

Unfortunately, there are no tools (which I know) that help maintain this separation. Therefore, you need to exercise due diligence in inheritance. It is very simple. Does virtual dtor and inaccessible / remote copy ctor and copy destination? You can inherit in public. Not? Avoid potential disturbances, use composition or personal inheritance.

A good class intended for inheritance will be protected by its copy elements to facilitate cloning in descendant classes.

Unfortunately, with third-party classes, you have no choice, since authors usually leave public copying participants, so the risk of fragmentation of objects remains. But you will not have the risk of incorrect deletion using the base pointer.

TL; DR no tools, just for the due diligence of the programmer.

+1
source share

All Articles