上一个标题:“我必须替换全局运算符 new 和 delete 以更改第三方代码中的内存分配策略吗?”
小故事: 我们需要在不改变其源代码的情况下替换第三方库中的内存分配技术。
很长的故事:
考虑进行大量动态分配的内存绑定应用程序(也许,几乎所有可用的系统内存)。我们使用专门的分配器,并在任何地方使用它们(shared_ptr
's、容器等)。我们对应用程序中分配的每一个内存字节拥有完全的控制权和权力。
此外,我们需要链接到第三方帮助库。那个讨厌的家伙以某种标准方式进行分配,使用默认运算符, 和new
ornew[]
或其他非标准的东西(让我们概括地说,我们不知道这个库如何管理它的堆分配)。delete
delete[]
malloc
如果这个帮助库的分配足够大,我们可能会遇到 HDD 抖动、内存碎片和对齐问题、内存bad_alloc
不足和各种问题。
我们不能(或不想)更改库源代码。
第一次尝试:
我们以前从未在发布版本中遇到过如此邪恶的“黑客”。使用覆盖运算符的第一个测试new
工作正常,除了:
- 我们不知道将来会遇到什么问题(这太可怕了)
- 我们的用户(甚至我们的分配器)现在必须以与我们相同的方式分配
问题:
- 有没有办法在不重载全局运算符的情况下挂钩这些分配?(仅限本地库的钩子?)
- ...如果我们不知道它到底使用了什么:
malloc
或者new
? 这个签名列表是否完整?(并且没有其他我们必须实现的东西):
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();
如果该库是动态的,会有什么不同?
编辑#1
如果可能,最好使用跨平台解决方案(看起来不太可能)。如果没有,我们的主要平台:
- Windows x86/x64 (msvc 10)
- Linux x86/x64 (gcc 4.6)
编辑#2
快 2 年过去了,很少有操作系统和编译器版本进化,所以我很好奇这个领域是否有一些新的和未开发的东西?有什么标准建议吗?操作系统细节?黑客?您今天如何编写需要大量内存的应用程序?请分享你的经验。