33

I have a hierarchy of base class and derived class. Base class has one virtual function which is overridden by derived class.

class Base
{  
public:  
    ~Base();    
    virtual void other_functionality() = 0;  
};

class Derived : public Base
{  
public:  
    ~Derived ();    
    void other_functionality() {//some code};  
};

Now if i do like this:

int main()
{
Base * P = new Derived ();
delete p;
return 0;
}

It gives error:
deleting object of polymorphic class type which has non-virtual destructor.

But with unique_ptr it passes without warning.

int main()
{
 std::unique_ptr<Base> p;
 p.reset(new Derived ());

return 0;
}

I know if I use virtual destructor. Warning with naked pointer will be solved. But question remains - why absence of virtual destructor shows problem with naked pointer and not with unique_ptr.

ypnos
  • 50,202
  • 14
  • 95
  • 141
gaurav bharadwaj
  • 1,669
  • 1
  • 12
  • 29
  • @AndriyTylychko unique_ptr exist in boost too and behavior of that and std::unique_ptr has lot of similarity. Isn't it. – gaurav bharadwaj Apr 25 '19 at 12:12
  • @ypnos do you not agree with above comment of mine? – gaurav bharadwaj Apr 25 '19 at 12:13
  • 2
    For the record, `clang` does complain: https://godbolt.org/z/qEp6Ts – Max Langhof Apr 25 '19 at 12:24
  • I think you will find your answer here: https://stackoverflow.com/questions/22124981/why-unique-ptr-doesnt-check-base-class-to-virtual-destructible – PStarczewski Apr 25 '19 at 12:24
  • 1
    @P.W I don't think this is a duplicate. At least, answers to both questions are different. (Answer to the original question is "because the Stadnard does not require such a check". Answer to this question is "because gcc supresses warnings for system headers".) – Daniel Langr Apr 25 '19 at 12:35
  • 1
    @DanielLangr: The question seemed the same in essence. But the answers do not directly address why the compiler does not issue a diagnostic. So I will reopen. – P.W Apr 25 '19 at 12:38
  • Why it is c++14 specific? This would apply to c++11 as well – Slava Apr 25 '19 at 12:58
  • @Slava very true, I guess the tag should just be removed, general c++ seems sufficient!? – Michael Kenzel Apr 25 '19 at 12:58
  • std::unique_ptr is in c++11/14. Now it can be debated why C++14 and not C++11. – gaurav bharadwaj Apr 25 '19 at 13:06
  • 1
    @gauravbharadwaj it's also in C++17 and pretty much guaranteed to be in C++20. I don't think this question is really specific to any particular version of the language at this point… – Michael Kenzel Apr 25 '19 at 13:14
  • 1
    @gauravbharadwaj I think it is fair that you tagged boost, and that other guy's comment was ridiculously worded. However I also believe the tag is wrong, this is a pure standard C++ matter and you do not even know about the existence of boost to answer this question. – ypnos Apr 26 '19 at 09:52

2 Answers2

40

Well, first of all, deleting a derived object through a base pointer when the base class does not have a virtual destructor is undefined behavior. Compilers are not required to diagnose undefined behavior…

That being said, the reason why this warning does not appear when using std::unique_ptr is most likely due to the fact that GCC does not report warnings that would appear in system headers.

Michael Kenzel
  • 15,508
  • 2
  • 30
  • 39
20

I cannot find a link, but I did see a discussion of this online, in GCC bug database.

The warning is issued on the actual delete expression. In the case of unique_ptr, the delete is called inside a system header file.

According to the discussion in that bug report, implementing C++ system libraries requires all sorts of compromises that result in various warnings. Therefore, the warnings are restricted inside system headers. That is the reason you won't see the warning you expect.

Update: and here it is, straight from the horse's mouth:

https://gcc.gnu.org/onlinedocs/cpp/System-Headers.html

The header files declaring interfaces to the operating system and runtime libraries often cannot be written in strictly conforming C. Therefore, GCC gives code found in system headers special treatment. All warnings, other than those generated by ‘#warning’ (see Diagnostics), are suppressed while GCC is processing a system header.