问题描述
如何为dll
重载new
和delete
运算符.我已将重载运算符作为dll的一部分进行编写,但与此dll
链接的客户端不使用overloaded new and delete
How to overload new
and delete
operator for a dll
. I have written overloaded operators as part of the dll , but client linking with this dll
does not use overloaded new and delete
推荐答案
在17.6.4.6/3节中,这是C ++标准要说的:
Here is what the C++ standard has to say about this, in section 17.6.4.6/3:
如果您仔细阅读该书,就可以准确说明您遇到的麻烦.这里发生一种捕获22".
If you read that carefully, it exactly explains the trouble you are having. There is a kind of "catch 22" happening here.
一方面,您无法在DLL内编译new/delete运算符的定义,因为无法动态链接重载的new/delete(这是因为在加载文件之前,在静态初始化期间可能需要new/delete). DLL,因此在DLL加载之前和之后,新的/删除的运算符会不一致,这是未定义的行为).
On one hand, you cannot have the definitions of your new/delete operators compiled inside the DLL because the overloaded new/delete cannot be linked dynamically (this is because new/delete might be needed during static initialization, prior to loading the DLL, so you would have inconsistent new/delete operators before and after the loading of the DLL, and that's undefined behavior).
另一方面,您不能只将新的/删除的运算符定义放在DLL头文件中,因为需要将它们标记为inline
才能满足一个定义规则(ODR),该规则反过来又,不满足上述条款.之所以要求它们不被标记为inline
可能是因为标记为inline
的函数定义具有无链接",导致每个翻译单元都使用其自己的编译版本(或作为内联扩展),通常这通常是可以的,但不能用于动态内存分配.
On the other hand, you cannot just put your new/delete operator definitions in your DLL header files, because they would need to be marked inline
in order to satisfy the One Definition Rule (ODR), which, in turn, doesn't satisfy the above clause. The requirement for them to not be marked inline
is probably there because a function definition marked inline
has "no linkage", resulting in each translation unit using its own compiled version of it (or as inline expansions), which, normally is OK, but not for dynamic memory allocation.
上述两个捕获都是出于以下事实的动机:为了正确起见,通常需要保证分配给new
的内存是由相应的delete
运算符释放的(即编译在一起",所以说话,或两者都默认).例如,如果您的new/delete运算符依赖于基础的malloc/free调用,则您依赖于DLL和可执行文件之间的调用new/delete运算符的转换单元使用的堆,则不能保证此堆将会是相同的(实际上,在Windows中尤其如此,这两个模块使用两个单独的堆进行动态内存分配).
Both of the above catches are motivated by the fact that, for correctness, there generally needs to be a guarantee that memory allocated with new
is deallocated with the corresponding delete
operator (i.e., "compiled together", so to speak, or both defaulted). For example, if your new/delete operators rely on an underlying malloc/free call, you rely on the heap used by the translation unit that called the new/delete operator, between a DLL and an executable, there is no guarantee that this heap will be the same (in fact, in Windows, in particular, it is not, the two modules use two separate heaps for dynamic memory allocations).
因此,正如Rook所说,解决您的问题的方法是不要那样做".不要重载DLL对象的new/delete运算符,因为没有干净的方法可以正确地执行此操作,无论您以哪种方式扭曲和旋转代码,它始终会归结为上述相同的问题.
So, the solution to your problem, as Rook puts it, is "don't do that". Don't overload the new/delete operators for DLL objects because there is no clean method to correctly do this, whichever way you twist and turn your code, it will always boil down to the same problem stated above.
您可以并且应该做的是对DLL对象使用工厂功能模式,并返回一个智能指针(例如std::shared_ptr
)和一个自定义删除程序,该删除程序依赖于将删除操作动态分配回给创建对象的站点.这是受到 Chad Austin 中的技术的启发.我在此处进行了类似的操作.
What you can and should do instead is to use a factory function pattern for your DLL objects and return a smart pointer (such as a std::shared_ptr
) with a custom deleter that relies on a dynamic dispatching of the deletion back to the site where the object was created. This is inspired by a technique from Chad Austin. I have done something very similar here.
这篇关于dll的新操作和删除操作符重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!