How to handle destructors in DLL exported interfaces

≯℡__Kan透↙ 提交于 2020-01-23 12:29:09

问题


I'm trying to export a class from a DLL. I read this article on doing so: http://www.codeproject.com/Articles/28969/HowTo-Export-C-classes-from-a-DLL

The "mature" approach suggest, that an abstract class is used, so I have:

// Header
class IFoo{
public:
    virtual int getBar() = 0;
}

class Foo: public IFoo {...}

DLLEXPORT IFoo* Create();
DLLEXPRT void Free(IFoo* inst);

//DLL cpp
IFoo* Create(){ return new Foo; }
void Free(IFoo* inst){ delete inst; }

What puzzles me: If I don't have a virtual destructor, then delete inst won't call Foos destructor and may leak memory. How am I supposed to handle that? The article does not give an answer to that.

Using virtual ~IFoo(){} is not possible, as that adds an implementation to IFoo which causes problems (explained in a answer to a question in the article for an inline virtual function) and virtual ~IFoo() = 0; fails with a linker error on the undefined symbol ~IFoo

What is the safe way to go? How should the Free/Release functions be implemented?


回答1:


First of all, let's note that the issue is specific to Visual Studio's handling of DLLs. GCC and Clang both have a stable ABI (Itanium ABI) which guarantees the compatibility of libraries compiled with different versions.

Now, as mentioned, the issue you face here is ABI instability, however parts of the ABI are stable (the virtual table layout) otherwise the strategy presented would simply not work.

Therefore, simply having a virtual destructor should work. There will be no name mangling issue because of the call via the virtual table.

Also, note that in modern C++ returning a raw pointer is a no-no, but name mangling prevents the use of a smart pointer...

// Foo.h
class Foo {
public:
    virtual int get() = 0;
    virtual ~Foo();

protected:
    Foo() = default;
    Foo(Foo&&) = default;
    Foo(Foo const&) = default;
    Foo& operator=(Foo) = default;
};

// WARNING: immediately capture this Foo* in a smart pointer,
//          or suffer from memory leak (and worse).
Foo* createFoo(); // factory behind

// Foo.cpp
Foo::~Foo() {} // not inline


来源:https://stackoverflow.com/questions/32444520/how-to-handle-destructors-in-dll-exported-interfaces

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!