gpt4 book ai didi

c++ - 导出构造函数的 DLL 有导致堆损坏的风险

转载 作者:行者123 更新时间:2023-11-30 02:45:37 25 4
gpt4 key购买 nike

我正在开发一个带有插件系统的程序,它允许用户以 DLL 文件的形式开发自己的模块。这些模块应该使用在应用程序的所有组件导入的 DLL 中定义的对象。这是示例对象的样子:

#include <boost/system/api_config.hpp>

#if defined BOOST_WINDOWS_API
#ifdef EXPORT
#define API __declspec(dllexport)
#else
#define API __declspec(dllimport)
#endif
#else
#define API
#endif

class A
{
public:
API A();
API virtual ~A();
};

所有 DLL 都是静态构建的(使用它们自己的 CRT)并且具有完全相同的编译标志。我知道通过 DLL 边界交换对象会很麻烦,所以我几乎在任何地方都使用 boost::shared_ptr。但是对象构造函数存在一个困难:如果我在堆栈上创建对象(从不同的 DLL),一切都按预期工作。但是如果我使用运算符 new,当对象被删除时堆会被破坏。

A a; // Works fine, no problem when the object goes out of scope.

A* b = new A();
delete b; // Causes heap corruption!

解决这个问题的正确方法是什么?我觉得如果我必须在对象的 DLL 中定义一个方法,例如 A* A::create() { return new A(); ,代码的可读性会降低。 }。在最坏的情况下,我正在考虑将 new 运算符设为私有(private),以确保用户不会使用它。

最佳答案

根据您对我的评论的回应:/MT/MTd 不与 DLL 配合良好(即使它们是默认的)。如果你想要使用 DLL 和动态分配,您必须使用/MD/MDd。当您使用 /MT/MTd 时,您有效地告诉系统为每个 DLL 使用单独的堆。意思就是在一个中分配,在另一个中删除会破坏堆。而当析构函数是虚函数时,实际的delete将在析构函数中,delete 表达式中。(实际问题是 mallocfree,由operator new()operator delete() 函数。)

解决这个问题的经典方法是使用工厂动态分配方法和静态或成员函数删除。另一种选择(没有尝试过,但我认为它会work) 是定义非内联 operator new()operator
delete()
成员,它只是转发给 mallocfree。(在 operator new 的情况下,当然,你必须检查你从 malloc 得到的指针不为空,然后抛出一个std::bad_alloc 如果是。)

但这些只是针对不应该出现的情况的变通方法存在。 /MD/MDd 一切正常,这是你应该使用什么(即使这意味着你不能合法在没有许可证的机器上部署调试版本用于 Visual Studios)。

关于c++ - 导出构造函数的 DLL 有导致堆损坏的风险,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24282912/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com