【问题标题】:Ignore globally overridden new/delete忽略全局覆盖的新建/删除
【发布时间】:2012-09-13 21:25:24
【问题描述】:

您好,我正在使用一个全局覆盖新/删除的库。但是我对这个库有一个问题,问题是它必须在main函数中手动初始化。

现在我正在尝试使用另一个库,在调用 main 之前初始化一些函数,不幸的是,这个库在这些函数中使用了 new。所以我收到错误,因为使用覆盖的 new/delete 关键字的内存管理器尚未初始化。

我真的很想使用默认的内存管理器,因为我想在这个库中添加单元测试。使用我要测试的库也被我的单元测试库使用的内存没有多大意义。

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

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

【问题讨论】:

  • 答案取决于平台和/或编译器。
  • 您是开发这两个库还是第三方库?如果您可以控制内存管理代码,我会偏离覆盖 new/delete 并以std::tr1::shared_ptr 的样式创建一个内存管理对象
  • @count0 我们开发了内存管理器库。它是具有高度优化的垃圾收集器的自定义内存管理器。我正在尝试使用 boost 测试库进行单元测试。
  • 然后使用内存管理对象,这是更简洁的设计,恕我直言。检查 Scott Meyers:有效的 C++:第 13 项
  • 不是我设计的。我刚开始在这里工作 ;-),我还不会质疑我的 Boss Programmer 的智慧。

标签: c++ visual-studio


【解决方案1】:

如果不修改库本身,我认为这是不可能的。我猜它是关于一个静态库(在 dll 中,被覆盖的 new/delete 将被 dll 中的函数指向。)

您可以使用命令(可视命令提示符)从静态库中删除 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 将包含每个符号的错位名称和该符号所在的 obj 的标识符。比如

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

14286 告诉你符号所在的 obj '标识符'。如果您在查找新/删除时遇到问题,可以运行:

 DUMPBIN /SYMBOLS input.lib > sym.txt

这将刷新到sym.txt 每个符号的损坏和未损坏名称。

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

现在,如果您不走运,您需要的其他符号可能与 new/delete 位于同一目标文件中。在这种情况下,您可以使用 this 之类的东西“破解”该库(例如将 new 重命名为 dewdelete 重命名为 nelete。)

【讨论】:

    【解决方案2】:

    如果覆盖是通过您可以使用的宏完成的

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

    如果它真的是通过函数覆盖完成的,那么您可以自己临时构建一个“新”宏,它调用一个放在其他地方的另一个名称的函数,它只调用标准函数。 宏在函数调用之前解析。

    【讨论】:

      【解决方案3】:

      你能把内存管理器的初始化放在一个共享库中吗?

      如果可能的话,您可以尝试强制库的初始化顺序(通过依赖项)在加载其他任何内容之前加载(并初始化)内存管理器。然而,这是一个非常脆弱(或特定)的解决方案,因为它将依赖于特定于平台的解决方法来强制共享库的初始化顺序。

      【讨论】:

      • 重写的关键字写在头文件中,所以我不能真正将它放在另一个库中,我真的很想使用默认的内存管理器,因为我想为此添加单元测试图书馆。使用我要测试的库也被我的单元测试库使用的内存没有多大意义。
      • 哦,使用依赖项强制初始化顺序是否可行,我不知道...但我仍然想使用默认的 new/delete,所以我可以在没有的情况下将单元测试添加到库中如果有人搞砸了,单元测试会自行崩溃。
      • 从您的问题来看,您似乎只有在初始化内存管理之前使用 ::new 和 ::delete 的问题。如果您想同时使用两者,则必须显式调用要测试的 new/delete。如果库设计者不为此使用命名空间,您可能会遇到麻烦,因为您不知道他们在库内部调用了什么方法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-14
      • 2016-05-07
      • 2020-03-30
      • 2015-04-25
      相关资源
      最近更新 更多