steinbergmedia / vst3sdk

VST 3 Plug-In SDK
Other
1.63k stars 162 forks source link

Should FUnknown have a virtual destructor? #21

Closed abique closed 5 years ago

abique commented 5 years ago

Hi,

I wonder why FUnknown does not have a virtual destructor?

Regards, Alexandre

rehans commented 5 years ago

Hey,

I ask the other way around: do you think it should have one? Why?

Cheers, René

(btw: github says 'rehans reacted with a laugh emoji'. No idea where this comes from. Maybe I pressed somewhere accidentally on my mobile phone ;)

abique commented 5 years ago

Yes it should have one.

If FUnknown did not have virtual methods, then not having a virtual destructor would avoid the vtable. But FUnknown has two virtual methods. So you have a vtable. What do you save by not having a virtual destructor in FUnknown? One entry in the vtable I guess. What do you get by having a virtual destructor in FUnknown? The guarentee that child class have a virtual destructor, and that your smart pointers will always call the right destructor.

Msixty7 commented 5 years ago

Hello,

The short answer is: binary compatibility. The VST interface basics are very similar to Microsoft (R) COM and also binary compatible. Adding a virtual destructor would change the vtable and destroy this compatibility. Although we would now give up this compatibility, we would destroy the compatibility with already released plug-ins and hosts.

A few more thoughts: The virtual destructor first becomes important in the class that implements addRef and release, because only here is it is allowed to destroy the object. Calling delete for a pointer to a VST interface is not a good idea in any other case!

class CMyClass: public FUnknown
{
public:
   CMyClass ();
   virtual ~CMyClass ();
   DECLARE_FUNKNOWN_METHODS // declares queryInterface, addRef and release
};

I can imagine that we offer a new macro DECLARE_FUNKNOWN_METHODS_2(className) which also contains the declaration of the constructor and the virtual destructor.

best regards Matthias

abique commented 5 years ago

Are you sure that adding the virtual dtor will break the ABI?

scheffle commented 5 years ago

Are you sure that adding the virtual dtor will break the ABI?

Yes, the visual studio compiler will break the ABI if you add a virtual destructor to FUnknown.

Spacechild1 commented 5 years ago

@abique Some compilers (e.g. GCC) will actually add two virtual functions for the destructor while others only add one (e.g. MSVC). If you you compile your plugin with MinGW and pass a pointer to a host compiled with MSVC, the latter will assume a different vtable layout and therefore call virtual methods at the wrong offset.

Another thing you have to avoid for binary compatible C++ interfaces is overloading virtual functions because their is no rule regarding the ordering in the vtable (it actually differs between compilers).

Finally, your method's parameters and return types must be plain C types.

In your implementation, however, you can do what you want, because the host never sees those vtables entries.

abique commented 5 years ago

Thanks for the explanation. I think that in such case the interface should have a default, non virtual destructor, but protected. That will ensure that you don't call delete on the object, and rely on the ref-counting.

What do you think?