Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clang & gcc don't warn about non-virtual base destructors for polymorphism when using smart pointers?

We know that if there are virtual functions then the base class destructor should be marked as virtual as well, otherwise it is undefined behavior when explicitly deleted with base class pointer if we hope to delete derived object with base class pointer the base destructor should be marked as virtual, otherwise it is undefined behavior.

For example,

struct Base {
  virtual void greet() { std::cout << "base\n"; }
};

struct Derived : public Base {
  virtual void greet() override { std::cout << "derived\n"; }
};

call

Base *b = new Derived;
b->greet();
delete (b);

clang(gcc similarly) will emit such a warning when -Wdelete-non-virtual-dtor:

delete called on 'Base' that has virtual functions but non-virtual destructor

But neither of them report warnings for smart pointers:

std::unique_ptr<Base> sb = std::make_unique<Derived>();
//   std::unique_ptr<Base> sb = std::unique_ptr<Derived>(new Derived);
sb->greet();

I guess this still leads to undefined behavior, right?

like image 251
Hongxu Chen Avatar asked Oct 12 '14 02:10

Hongxu Chen


People also ask

What Clang is used for?

The Clang tool is a front end compiler that is used to compile programming languages such as C++, C, Objective C++ and Objective C into machine code. Clang is also used as a compiler for frameworks like OpenMP, OpenCL, RenderScript, CUDA and HIP.

What does Clang stand for?

Clang definitionA loud, resonant, metallic sound.

Is Clang better than GCC?

GCC supports more traditional languages than Clang and LLVM, such as Ada, Fortran, and Go. GCC supports more less-popular architectures, and supported RISC-V earlier than Clang and LLVM. GCC supports more language extensions and more assembly language features than Clang and LLVM.

Is it pronounced Clang or Clang?

The official pronunciation is "klang" with a hard C: http://lists.llvm.org/pipermail/llvm-dev/2008-July/015629.ht...


2 Answers

Yes, it's still undefined behavior. The problem is that the delete call happens inside std::default_delete, which is inside a system header. By default, the compiler doesn't generate warnings for code in system headers.

If you pass -Wsystem-headers, you'll see the warning. Unfortunately, it's buried inside a pile of other warnings.

like image 160
T.C. Avatar answered Nov 06 '22 10:11

T.C.


Not mentioned yet by the other answers:

This problem only exists for unique_ptr, not for the shared_ptr.

Both of these smart pointers can have custom deleters; however unique_ptr defaults to deleting the base pointer, and shared_ptr defaults to deleting the derived pointer (if you used make_shared<Derived> or equivalent).

Another way to solve the problem is to supply your own custom deleter for unique_ptr that deletes the derived pointer. This might be a good solution for cases where you want to avoid the overhead of introducing a vtable.

Further reading: unique_ptr deleter, shared_ptr deleter

like image 45
M.M Avatar answered Nov 06 '22 11:11

M.M