如何处理 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
我正在尝试从 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