如何控制第三方库的代码的内存分配策略是什么?(How to control memory alloc

2019-09-01 23:46发布

上一个标题:“我必须更换全球运营商new和delete改变内存分配策略中的第三方代码吗?”

简单地说:我们需要替换第三方库内存分配技术,无需改变它的源代码。

很长的故事:

考虑内存限制的应用程序,使得庞大的动态分配(也许是,几乎所有可用的系统内存)。 我们使用专门的分配器,到处都使用它们( shared_ptr的,容器等)。 我们有在我们的应用程序分配内存的每一个字节总量控制和功率。

此外,我们需要对第三方助手库链接。 那个讨厌的家伙使得一些标准的方式分配,使用默认的运营商newnew[] deletedelete[]malloc或别的东西,非标准(让我们一概而论说我们不知道这个库如何管理它的堆分配)。

如果这个辅助库使得分配是足够大的,我们可以得到HDD颠簸,内存碎片和路线问题,出内存不足bad_alloc S和各种各样的问题。

我们不能(或不愿)来改变库的源代码。

第一次尝试:

我们从来没有过这样邪恶的“黑客”,在发布之前建立。 与压倒一切的操作者首先测试new不同之处在于,做工精细,:

  • 我们不知道什么陷阱等待我们的未来(这是可怕的)
  • 我们的用户(甚至我们的分配器)现在必须分配我们做同样的方式

问题:

  1. 是否有办法挂钩这些分配没有超载全球运营商? (仅限本地LIB-挂钩?)
  2. ...如果我们不知道它到底是什么用途: mallocnew
  3. 是签名的这份名单是否完整? (并且没有其他的事情,我们必须执行):

     void* operator new (std::size_t size) throw (std::bad_alloc); void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) throw(); void* operator new (std::size_t size, void* ptr) throw(); void* operator new[] (std::size_t size) throw (std::bad_alloc); void* operator new[] (std::size_t size, const std::nothrow_t& nothrow_value) throw(); void* operator new[] (std::size_t size, void* ptr) throw(); void operator delete (void* ptr) throw(); void operator delete (void* ptr, const std::nothrow_t& nothrow_constant) throw(); void operator delete (void* ptr, void* voidptr2) throw(); void operator delete[] (void* ptr) throw(); void operator delete[] (void* ptr, const std::nothrow_t& nothrow_constant) throw(); void operator delete[] (void* ptr, void* voidptr2) throw(); 
  4. 不同的东西,如果该库是动态的?

编辑#1

跨平台的解决方案是优选的(如果可能看起来不太可能)。 如果不是这样,我们的主要平台:

  • 的Windows 86/64(MSVC 10)
  • 于Linux x86 / 64(GCC 4.6)

编辑#2

近2年过去了,几个操作系统和编译器版本已经进化了,所以我很好奇,如果有这方面的一些新的和未知? 任何标准的建议? OS-具体情况如何? 黑客? 你怎么写内存渴应用的今天? 请分享你的经验。

Answer 1:

唉,我的同情。 这将取决于很多你的编译器,你的libc等一些橡胶符合道路的战略已经“工作”在过去的不同对我们度(/我括号为downvotes)分别是:

  • operator new / operator delete你的建议重载-但请注意一些编译器是挑剔没有throw()的规格,还真有些想他们,有的希望他们新的,但不是删除等(我有一个巨大的平台,具体#if / #elif对所有的,我们正在处理的4+平台块现在)。
  • 另外值得一提:你通常可以忽略安置的版本,他们不分配。
  • 看看__malloc_hook和朋友 -注意,这些已被弃用,并具有线程竞态条件-但他们在新的人很好/删除往往会在条款中实现malloc (但不总是)。
  • 提供了一个替代malloccallocrealloc ,和free和让你连接ARGS在正确的顺序,使覆盖发生(这是海湾合作委员会建议这几天,虽然我已经在那里这是不可能做到的情况下,我不得不使用过时的__malloc_hook ) -再次, newdelete 往往在这些方面来实现,但并非总是如此。
  • 避免所有的标准分配方法( operator newmalloc在“我们的代码”等),使用自定义功能,而不是-不是很容易与现有的代码库。
  • 追查库的作者,并提供一个野蛮殴打有礼貌的请求或补丁来改变自己的图书馆,让您可以指定不同的分配器(它可能会比这样做自己更快) -我认为这导致了“客户的基本规则始终指定分配或不分配”与我写的库。

请注意,这不是什么标准说应该发生一个方面回答,只是我的经验。 我比一些越野车/破碎的编译器和libc中的实现,在过去更多的工作,所以YMMV。 我也有工作相当“封闭系统”,而不是所有的担心便携性对于任何特定应用的奢侈品。

关于动态库:目前我在一个位在这方面我自己捏的; 我们的“应用程序”被载入作为动态.so ,我们必须非常小心,以传递任何delete / free请求回默认的分配,如果他们不从我们这里来了。 目前的解决方法就是封锁了我们分配到一个特定的区域:如果我们得到一个删除/免费从该地址范围内,我们派遣我们的处理程序,否则返回至默认......我甚至用(恐怖玩弄)检查呼叫方的地址,看它是否在我们的地址空间的想法。 (要去与这样黑客吊杆升高,虽然概率。)

这可能是一个有用的策略,即使你是在处理铅和你使用一个外部库:标签或限制或以其他方式确定自己的allocs莫名其妙地(甚至去,至于让你了解allocs的列表),并再传给任何未知数。 所有这一切都具有丑陋的副作用和局限性,虽然。

(期待其他的答案!)



Answer 2:

如果不能够修改库的源代码 - 或者,更好的,能够影响该库的作者进行修改 - 我说你的运气了。

有一些事情库可能可以做(甚至无意),使其不受你可能会使用任何策略 - 或者,在最坏的情况下,有结果,你的使用将使图书馆不稳定,也可能使你的程序不稳定。 比如用自己的自定义的分配,提供自己的全球版本operator new()operator delete()覆盖的运营商在个别类等

这可能会工作的战略是与库供应商合作,并提出一些修改。 (从末)的修改将达到能够将它指定使用allocator初始化库。 该库的努力是潜在显著(具有触摸到了动态分配存储器,其使用标准的集装箱等所有功能,),但并不难治 - 在其整个代码使用所提供的分配器(或合理的默认值)。

不幸的是,这是在与你的要求不修改库赔率 - 我怀疑是满意,尤其是在限制你所概述(内存渴,托管在Windows / Linux等)的机会。



Answer 3:

该类库中取得分配不能做到,但你可以使用新的布局从该第三方库分配类,即你可以分配内存,并有那些呼吁分配memory.So这样即便类有类的构造函数自己的新的运营商它wouldnt被调用.Howvwer,里面的类操作的内存分配给未曝光的内部类或原语会使用第三方库的分配方案进行; 这不能被改变,除非第三方库允许你指定一个像STL容器分配器



文章来源: How to control memory allocation strategy in third party library code?