What is the general guidance with using shared_ptr on interfaces that do not have virtual destructor?


Take the following code sample:

class IFoo
{
public:
    virtual void M1() = 0;
};

class Foo : public IFoo
{
public:
    void M1() {}
    Foo() { std::cout << "Foo constructor\n";}
    ~Foo(){std::cout << "~Foo destructor\n";}
};


I think we all know that this is not safe:

{
    IFoo *pFoo = new Foo();
    delete pFoo;
}

Since IFoo is missing a virtual destructor, then ~Foo() will not be invoked in the above case.


So let's switch to using std::shared_ptr

{
    std::shared_ptr<IFoo> spFoo(new Foo());
}

std::shared_ptr has a templated constructor that creates a "deleter".  So when "spFoo" goes out of scope, the ~Foo destructor is properly invoked even though it's of type shared_ptr<IFoo>.  But since my code targets older compilers, I have made use of Boost.  But attempting this:

{
    boost::shared_ptr<IFoo> spFoo(new Foo());
}

Generates a lot of scary warnings when compiling with -Wall.

In file included from /home/jselbie/boost_1_57_0/boost/checked_delete.hpp:15:0,
                 from /home/jselbie/boost_1_57_0/boost/smart_ptr/shared_ptr.hpp:26,
                 from /home/jselbie/boost_1_57_0/boost/shared_ptr.hpp:17,
                 from main.cpp:9:
/home/jselbie/boost_1_57_0/boost/core/checked_delete.hpp: In instantiation of ‘void boost::checked_delete(T*) [with T = Foo]’:
/home/jselbie/boost_1_57_0/boost/smart_ptr/detail/shared_count.hpp:134:38:   required from ‘boost::detail::shared_count::shared_count(Y*) [with Y = Foo]’
/home/jselbie/boost_1_57_0/boost/smart_ptr/shared_ptr.hpp:271:47:   required from ‘void boost::detail::sp_pointer_construct(boost::shared_ptr<X>*, Y*, boost::detail::shared_count&) [with T = IFoo; Y = Foo]’
/home/jselbie/boost_1_57_0/boost/smart_ptr/shared_ptr.hpp:349:58:   required from ‘boost::shared_ptr<T>::shared_ptr(Y*) [with Y = Foo; T = IFoo]’
main.cpp:36:44:   required from here
/home/jselbie/boost_1_57_0/boost/core/checked_delete.hpp:34:5: warning: deleting object of polymorphic class type ‘Foo’ which has non-virtual destructor might cause undefined behaviour [-Wdelete-non-virtual-dtor]


Now despite the warning about the non virtual destructor, the correct behavior of having ~Foo() invoked works. The interesting thing is that marking the destructor of the *derived* class (virtual ~Foo) makes the warning go away.  It's like it's warning me that if I ever inherit from Foo, then I might run into issues - not of any immediate problems.

Should I never user shared_ptr with interface pointers that lack a virtual destructor?  Always declare a virtual destructor?  What is the guidance here?

jrs