新的和删除运算符重载为DLL

时间:2012-08-07 12:54:36

标签: c++ window new-operator

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

2 个答案:

答案 0 :(得分:7)

以下是C ++标准在第17.6.4.6/3节中所说的内容:

  

使用程序的定义(new / delete运算符)而不是实现提供的默认版本。这种替换发生在程序启动之前。程序的定义不应指定为inline。无需诊断。

如果您仔细阅读,那么它确切地解释了您遇到的麻烦。这里发生了一种“捕获22”。

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

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

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

因此,正如鲁克所说,解决问题的方法是“不要那样做”。不要重载DLL对象的新/删除操作符,因为没有干净的方法来正确地执行此操作,无论您扭转和转动代码,它总是归结为上述相同的问题。

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

答案 1 :(得分:0)

您可以尝试编写自己的malloc并删除函数,然后创建一个C定义,它基本上包含覆盖new和delete的代码,并调用这些自定义malloc和delete函数。

这样你可以做一些事情,比如

MODULE_START()
// CODE HERE

MODULE_END()

这应该可以顺利进行。