是否可以在任何地方替换全球“运营商new()”?

时间:2010-01-20 19:54:39

标签: c++ memory-management linker

我想替换全局operator new()operator delete()(及其所有变体),以便执行一些内存管理技巧。我希望我的应用程序中的所有代码都使用自定义运算符(包括我自己的DLL中的代码以及第三方DLL)。我已经阅读了一些内容,链接器将选择链接时看到的第一个定义(例如,如果包含您的自定义operator new()的库首先链接,它将“击败”与CRT的链接)。有没有办法保证会发生这种情况?有什么规则,因为这确实是一个多重定义的符号(例如,void* operator new(size_t size)在全局命名空间中有两个定义)?

可能与CRT静态链接的第三方DLL怎么样?即使它们与CRT动态链接,我是否可以通过某种方式将其与我的 operator new()相关联?

2 个答案:

答案 0 :(得分:7)

C ++标准明确允许您编写自己的全局运算符new和delete(以及数组变体)。该连接器具有使其工作,但究竟是如何达到的实现者(例如,像弱的外部可供应的东西当且仅当一个已不存在有用)。

就DLL来说,它会变得棘手:静态链接的DLL显然不会在没有大量额外工作的情况下使用你的代码。静态链接意味着它已经有一个复制到DLL中的库代码的副本,并且DLL中使用它的任何代码都具有已经编码的代码的地址。为了解决这个问题,你必须弄清楚DLL的代码在哪里,并动态修补调用它的所有代码来调用你的代码。

如果DLL动态链接到标准库,它只会稍微容易一些 - 导入表仍然会编码DLL的名称,并在该DLL中提供所需的功能。就是可以被得到(例如,具有类似微软的Detours library),但它有点不平凡的(但肯定比当DLL链接标准库静态容易)。

答案 1 :(得分:3)

编辑:在重新阅读问题后,我意识到您的重点是第三方组件。那么在这种情况下答案是否定的。涉及的变量太多了。


(参考替换你自己代码中的“新”)简短的回答是肯定的。这是执行自己的内存管理的系统中的常见技巧。正如你可能已经猜到的那样,这是一个非常棘手的事情,如果你不小心的话,很容易在你的脸上爆炸,但它肯定是合理的,并被许多软件使用。 (我记得读过一些在Doom 3 SDK中执行此操作的代码)

至于在第三方DLL中替换new和delete,这不会发生(至少不安全)。首先,你怎么知道他们甚至使用new和delete?更不用说他们可能正在做他们自己的这种技术的变体,并依靠它的一些副作用来正常运作。即使你现在正在使用它,你怎么知道该组件的某些未来版本不会破坏它?您可以随心所欲地使用自己的记忆,但为了您和您的用户的理智,请不要尝试微观管理其他二进制文件的内存。

相关问题