忽略全局重载的new/delete

7

你好,我正在使用一个覆盖了全局new/delete的库。但是我遇到了这个库的一个问题,问题在于它必须在主函数中手动初始化。

现在我正在尝试使用另一个库,在调用main函数之前初始化几个函数,不幸的是,这个库在这些函数中使用了new。因此,我会因为未初始化使用重载的new/delete关键字的内存管理器而出现错误。

我真的很想使用默认的内存管理器,因为我想为这个库添加单元测试。如果使用我想要测试的库和我的单元测试库都使用相同的内存,那就没有什么意义了。

所以我的问题是,是否可能在包含第二个库时忽略全局覆盖的new/delete,并仅使用默认的new/delete?

我正在使用Windows 7上的Visual Studio 2010和标准C++编译器。


答案将取决于平台和/或编译器。 - atzz
你是同时开发这两个库还是它们是第三方的?如果你掌控内存管理代码,我建议不要覆盖new/delete,而是按照std::tr1::shared_ptr的风格创建一个内存管理对象 - count0
我并没有设计它。我刚刚开始在这里工作 ;-),我暂时不会质疑我的老板程序员的智慧。 - NomenNescio
似乎你的内存管理库设计得很糟糕。由于全局对象可以在它们的构造函数中使用new/delete,所以该库将无法与其他正确的C++代码一起使用。因此,count0的答案可能是正确的:内存管理库应该支持混合模式,在这种模式下,一些对象使用原始的new/delete函数,而库不会干扰它们,或者它应该通过特定于平台的方式非常早地初始化。在main()中初始化太晚了。 - h2stein
你可以尝试使用placement new或类特定的new操作符来解决库的问题。这取决于库的设计方式以及你想要测试的代码的外观。 - h2stein
显示剩余2条评论
3个回答

1
我认为这是不可能的,除非修改库本身。我猜这是关于静态库的(在dll内部,重载的new/delete将由dll内部的函数指向。)
您可以使用命令(Visual命令提示符)从静态库中删除一个obj文件:
  LIB /REMOVE:obj_to_remove /OUT:removed.lib input.lib

要找出要删除的 obj,首先运行:

  DUMPBIN /ARCHIVEMEMBERS input.lib

您将看到诸如

这样的行。

    Archive member name at 14286: /0  compilation.dir\objfile1.obj

14286 '标识' obj 文件。要查看每个符号的位置,请运行:

 DUMPBIN /LINKERMEMBER:1 input.lib > members.txt

查找新建/删除。 members.txt 文件将包含每个符号的混淆名称和该符号所在对象的标识符。例如:

    14286 ?_Rank@?$_Arithmetic_traits@C@std@@2HB

14286 告诉你符号所在的 obj 'identifier'。如果你找不到 new/delete,可以运行以下命令:

 DUMPBIN /SYMBOLS input.lib > sym.txt

这将把每个符号的混淆和未混淆名称刷新到sym.txt中。

最后,通过在我们的示例中将obj_to_remove替换为compilation.dir\objfile1.obj,使用上面的LIB命令删除obj文件,并链接到removed.lib

现在,如果你不幸的话,你需要的其他符号可能与new/delete在同一个对象文件中。在这种情况下,你可以使用类似this的方法“黑客”lib(例如将new重命名为dew,将delete重命名为nelete)。


0

如果使用宏进行覆盖,您可以使用

#pragma push_macro ("new")
#undef new
...code with standard new here ...
#pragma pop_macro ("new")

如果确实是通过函数重载完成的,那么您可以暂时自己构建一个“新”的宏,调用另一个名称放置在其他地方的函数,该函数只是调用标准函数。宏在函数调用之前解析。


0
你能把内存管理器的初始化放到共享库中吗?
如果可以的话,你可以尝试通过依赖关系来强制加载(和初始化)内存管理器,以确保在加载其他内容之前先加载内存管理器。但这是一种非常脆弱或特定的解决方案,因为它将取决于平台特定的解决方案来强制共享库初始化的顺序。

重写的关键字写在头文件中,所以我不能把它放到另一个库中,而且我真的很想使用默认的内存管理器,因为我想向这个库添加单元测试。使用我想要测试的库使用的内存来进行单元测试并不太合理。 - NomenNescio
哦,通过依赖项强制初始化顺序可能会起作用,我不确定...但我仍然想使用默认的new/delete,这样我就可以向库添加单元测试,而无需担心单元测试如果有人出错会崩溃。 - NomenNescio
从你的问题中看来,似乎你只是在内存管理初始化之前使用::new和::delete时遇到了问题。如果你想同时使用两者,你必须显式地调用你想要测试的new/delete。如果库设计者没有为此使用命名空间,那么你可能会遇到麻烦,因为你不知道他们在库内部调用什么方法。 - count0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接