<div dir="ltr">On Thu, Oct 3, 2013 at 2:43 AM, emmanuel.attia <span dir="ltr"><<a href="mailto:emmanuel.attia@philips.com" target="_blank">emmanuel.attia@philips.com</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
Sorry to dig out an old topic, but there is one case where delete on<br>
abstract with non-virtual is safe.<br>
If you make a component model for plugin managment and you don't want to<br>
enforce any compiler / compiler settings / runtime settings, you have to<br>
delegate the delete operator to make sure deletion happen in the same module<br>
as allocation.<br>
<br>
Here is a small example of this: (suppose main.cpp and toto.cpp are in<br>
different module, for instance main.exe and toto.dll).<br>
<br>
<br>
// common.h (visible in main.cpp and toto.cpp)<br>
struct my_destroy_interface<br>
{<br>
    virtual void Destroy() = 0;<br>
<br>
    inline void operator delete (void * ptr) {<br>
        if (ptr != NULL) static_cast<my_destroy_interface<br>
*>(ptr)->Destroy();<br></blockquote><div><br></div><div>This has undefined behavior. You're calling a virtual function on an object whose lifetime has ended (the destructor has already been called).</div><div><br>
</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
    }<br>
};<br>
<br>
my_destroy_interface * createToto();<br>
<br>
// toto.cpp<br>
struct my_destroy_default_impl : public my_destroy_interface<br>
{<br>
protected:<br>
    virtual ~my_destroy_default_impl()<br>
    {<br>
        printf("~my_destroy_default_impl()\n");<br>
    }<br>
<br>
    virtual void Destroy()<br>
    {<br>
        ::delete this;<br>
    }<br>
};<br>
<br>
struct Toto : public my_destroy_default_impl<br>
{<br>
protected:<br>
    ~Toto()<br>
    {<br>
        printf("~Toto()\n");<br>
    }<br>
};<br>
<br>
my_destroy_interface * createToto()<br>
{<br>
    return new Toto;<br>
}<br>
<br>
// main.cpp<br>
int main(int argc, char* argv[])<br>
{<br>
    delete createToto();<br></blockquote><div><br></div><div>This has undefined behavior (you're using 'delete', the static and dynamic types don't match, and your base class does not have a virtual destructor).</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
        return 0;<br>
}<br>
<br>
Result:<br>
~Toto()<br>
~my_destroy_default_impl()<br>
<br>
<br>
This is perfectly valid</blockquote><div><br></div><div>Nope. See above. Or try giving my_destroy_interface a user-declared (non-virtual) destructor, and watch as it either gets called twice or your program starts to die due to a pure virtual function call (depending on implementation details).</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> but gets a warning:<br>
warning : delete called on 'my_destroy_interface' that is abstract but has<br>
non-virtual destructor [-Wdelete-non-virtual-dtor]<br>
<br>
If I would have put the virtual destructor in the interface definition,<br>
"delete createToto()" would have called ~Toto(), but also "::delete this".<br>
<br>
Usually this is not an issue because in this kind of component model, the<br>
practice is to call ->Destroy() (more oftently called Release() ) directly.<br>
<br>
Using the delete operator allows to combine this kind of objects with smart<br>
pointer classes, without the smart pointer classes having any knowledge that<br>
they handle objects from another "plugin".<br>
<br>
An alternative to this without warning would be to:<br>
* add an empty virtual destructor to the interface.<br>
* call ::operator delete(this) instead of ::delete this in<br>
my_destroy_default_impl::Destroy to trigger only memory freeing and not<br>
destructor calling.<br>
Both method are valid but not having to add a empty virtual destructor to<br>
each interface is nice (plus interface are not supposed to have implemented<br>
functions)<br>
<br>
One could live with ignoring this warning, but I guess when the operator<br>
delete is custom, it is safe not to emit this warning.<br></blockquote><div><br></div><div>No, the warning is always correct.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

Best regards,<br>
<br>
Emmanuel<br>
<br>
<br>
<br>
--<br>
View this message in context: <a href="http://clang-developers.42468.n3.nabble.com/is-delete-on-abstract-with-non-virtal-ever-safe-tp4025653p4034847.html" target="_blank">http://clang-developers.42468.n3.nabble.com/is-delete-on-abstract-with-non-virtal-ever-safe-tp4025653p4034847.html</a><br>

Sent from the Clang Developers mailing list archive at Nabble.com.<br>
<div class="HOEnZb"><div class="h5">_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@cs.uiuc.edu">cfe-dev@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br>
</div></div></blockquote></div><br></div></div>