代码之家  ›  专栏  ›  技术社区  ›  user12345

是否可以在任何地方替换全局“operator new()”?

  •  8
  • user12345  · 技术社区  · 16 年前

    我想换全球的 operator new() 和 operator delete() (以及它们的所有变体)以执行一些内存管理技巧。我希望应用程序中的所有代码都使用自定义运算符(包括我自己的DLL和第三方DLL中的代码)。我读到的意思是链接器将选择链接时看到的第一个定义(例如,如果库包含您的自定义 运算符New() 首先链接,它将“击败”与CRT的链接)。有什么办法保证这一切会发生吗?因为这是一个乘法定义的符号(例如, void* operator new(size_t size) 全局命名空间中有两个定义?

    第三方dll与crt静态链接怎么样?即使它们与CRT动态链接,我是否可以让它们与 我的 运算符New() 是吗?

    2 回复  |  直到 16 年前
        1
  •  7
  •   Jerry Coffin    16 年前

    C++标准明确地允许您编写自己的全局运算符new和Delphi(以及数组变体)。链接器必须使其工作,尽管具体如何取决于实现者(例如,弱外部的东西可以有助于提供一些东西,如果并且仅当一个还没有出现的时候)。

    至于DLL,这将是一个棘手的问题:一个静态链接的DLL显然不会在没有大量额外工作的情况下使用您的代码。静态链接意味着它已经将库代码的副本复制到了dll中,并且dll中使用的任何代码的地址都已编码。为了解决这个问题,您必须找出new的代码在dll中的位置,并动态地修补所有调用它的代码以调用您的代码)。

    如果DLL动态链接到标准库,那么只会稍微容易一点——导入表仍然对DLL的名称进行编码,并在该DLL中提供所需的函数。这是可以绕过的(例如,用微软的 Detours library )但这有点不平凡(尽管肯定比动态链接库静态链接标准库更容易)。

        2
  •  3
  •   Toji    16 年前

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


    (指在你自己的代码中替换“新的”)简短的回答是“是”。这是执行自己内存管理的系统中的一个常见技巧。正如你可能已经猜到的,要想正确是一件非常棘手的事情,如果你不小心的话,它很容易在你的脸上爆炸,但是它确实是合理的,并且被许多软件使用。(我记得读过一些在Dooms3sdk中实现这一点的代码,例如)

    至于替换第三方dll中的new和delete,这是不会发生的(至少不安全)。首先,你怎么知道他们甚至使用“新建”和“删除”?更不用说,他们可能正在做他们自己的这项技术的变体,并且依赖它的一些副作用来正常工作。即使你现在就开始工作了,你怎么知道将来的组件版本不会破坏它呢?你可以随心所欲地使用你自己的内存,但是为了你和你的用户的理智,请不要试图微管理其他二进制文件的内存。