如何处理 DLL 导出接口中的析构函数

How to handle destructors in DLL exported interfaces

我正在尝试从 DLL 中导出 class。我阅读了这篇文章:http://www.codeproject.com/Articles/28969/HowTo-Export-C-classes-from-a-DLL

"mature" 方法建议使用抽象 class,所以我有:

// 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; }

令我困惑的是:如果我没有虚拟析构函数,那么 delete inst 将不会调用 Foos 析构函数并且可能会泄漏内存。我该如何处理?文章没有给出答案。

使用 virtual ~IFoo(){} 是不可能的,因为这会向 IFoo 添加一个实现,这会导致问题(在对内联虚函数的文章中的问题的回答中进行了解释)并且 virtual ~IFoo() = 0; 失败并显示未定义符号的链接器错误 ~IFoo

安全的方法是什么? Free/Release的功能应该如何实现?

首先,请注意该问题特定于 Visual Studio 对 DLL 的处理。 GCC 和 Clang 都有一个 stable ABI (Itanium ABI) 来保证不同版本编译的库的兼容性。

现在,如前所述,您在这里面临的问题是 ABI 不稳定,但是部分 ABI 是 stable(虚拟 table 布局),否则所提供的策略根本行不通。

因此,只需要一个 virtual 析构函数就可以了。由于通过虚拟 table.

进行调用,因此不会出现名称混淆问题

此外,请注意,在现代 C++ 中返回原始指针是禁止的,但名称重整会阻止使用智能指针...

// 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