c++ - dll 的 new 和 delete 运算符重载

标签 c++ window new-operator

如何为 dll 重载 newdelete 运算符。我已经将重载运算符作为 dll 的一部分编写,但是与此 dll 链接的客户端不使用 overloaded new and delete

最佳答案

这是 C++ 标准在第 17.6.4.6/3 节中对此的说明:

The program's definitions (of the new / delete operators) are used instead of the default versions supplied by the implementation. Such replacement occurs prior to program startup. The program's definitions shall not be specified as inline. No diagnostic is required.

如果您仔细阅读,它恰好解释了您遇到的问题。这里发生了一种“第 22 条军规”。

一方面,您不能在 DLL 中编译 new/delete 运算符的定义,因为重载的 new/delete 不能动态链接(这是因为在静态初始化期间可能需要 new/delete,然后再加载DLL,所以在加载 DLL 之前和之后你会有不一致的新/删除运算符,这是未定义的行为)。

另一方面,您不能只将 new/delete 运算符定义放在 DLL 头文件中,因为它们需要标记为 inline 以满足单一定义规则 (ODR) ,这反过来又不满足上述条款。要求它们不被标记为 inline 可能是因为标记为 inline 的函数定义“没有链接”,导致每个翻译单元使用它自己的编译版本(或作为内联扩展),这通常是可以的,但不适用于动态内存分配。

上述两个捕获的动机是,为了正确性,通常需要保证使用 new 分配的内存被相应的 delete 释放运算符(即“一起编译”,可以这么说,或者两者都默认)。例如,如果你的 new/delete 运算符依赖于底层的 malloc/free 调用,你依赖于调用 new/delete 运算符的翻译单元使用的堆,在 DLL 和可执行文件之间,不能保证这个堆将是相同的(实际上,在 Windows 中,特别是,它不是,这两个模块使用两个单独的堆进行动态内存分配)。

因此,正如 Rook 所说,解决问题的方法是“不要那样做”。不要为 DLL 对象重载 new/delete 运算符,因为没有干净的方法可以正确地执行此操作,无论您以何种方式扭曲和转换代码,它总是会归结为上述相同的问题。

您可以而且应该做的是为您的 DLL 对象使用工厂函数模式,并返回一个智能指针(例如 std::shared_ptr)和一个依赖于将删除动态分派(dispatch)回创建对象的站点。这是受到来自 Chad Austin 的一项技术的启发。 .我做过非常相似的事情here .

关于c++ - dll 的 new 和 delete 运算符重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11846511/

相关文章:

c# - windowStyle=None 的不可调整大小的窗口

c++ - 新的运算符帮助、类型说明符和其他错误

c++ - operator new 重载和对齐

c++ - 函数模板无法编译

c++ - 来自 lineEdit 的 int 输入

c++ - 将 C++ dll 导出到 Delphi 程序

c++ - 如何处理外部应用程序窗口?多功能 Controller

java - 如何在load方法中调用Window?

c++ - malloc.c :2372: sysmalloc: Assertion

c++ - 更改函数中的全局变量