在混合C / C ++程序中调整malloc和new的“正确”方法是什么?

我有一个混合的C / C ++程序。 它包含一个以C / C为目标的flex / bison解析器,其余为C ++。

作为C,生成的解析器和扫描程序使用mallocreallocfree管理它们的内存。 它们足以暴露钩子,允许我提交我自己的这些函数的实现。 正如您所料,(C ++)程序的其余部分“希望”使用newdelete等。

做一点研究似乎表明相关标准并不能保证这种混合应该起作用。 特别是C“堆”不一定是C ++“自由区”。 看来这两个方案可以互相践踏。

最重要的是,有一天(很快),该程序可能希望集成一个自定义的堆实现,例如tcmalloc ,由C和C ++使用。

在这里做什么是“正确”的事情?

鉴于需要集成tcmalloc(它解释了如何与C程序链接),我很想在C ++内存管理中找到一些跨类型,跨线程,跨所有重载/挂钩/任何内容。 有了这个,我可以将所有C ++分配/释放调用指回它们的C等价物(反过来又落在tcmalloc上。)

是否存在这样的泛星系全局C ++钩子? 可能它已经在做我想要的,类似于ios_base::sync_with_stdio默认秘密地与iostream和stdio结合?

我对谈论stdio与iostreams以及切换解析器生成器以及使用C ++ flex / bison骨架(它们引入独立的头痛)并不感兴趣。

编辑 :请包括支持您的答案的C ++标准的那些部分的名称。

该标准确保混合两种分配变体将起作用。 它不允许的内容就是在new内存上调用内存,因为它们可能会使用完全不同的两种类型的竞技场。

如果你记得为给定的内存块调用正确的释放函数,你会没事的。 如果你遵守规则他们不会互相践踏,如果你不遵守规则,那么从技术上讲, 你是在践踏,而不是他们:-)


C ++ 11标准的控制部分是20.6.13 C library ,其中陈述,解释:

  • 基于C标准提供了函数callocmallocfreerealloc
  • 这些函数不使用::operator new()::operator delete()
  • 这允许遗产C的东西使用不同的内存竞技场然后正常的C ++内存分配。

根据你最终提出的建议,第二个要点是有趣的,放入tcmalloc来替换C遗产函数并让C ++也使用它。

标准中有一个脚注,解释了为什么他们不使用let malloc() call ::operator new()

目的是通过调用std :: malloc()或std :: calloc()来实现operator new()。 换句话说,他们希望避免循环依赖。

但是,虽然它允许 operator new()调用malloc() ,但我不确定标准实际上是否需要它。 因此,为了安全起见,您可能希望将tcmalloc注入C C ++区域。

你已经表明你已经知道如何为C做了。对于C ++,它可以通过在代码中简单地提供整个全局operator new()/delete()函数来完成,适当地编写为调用tcmalloc 。 C ++标准在3.7.4 Dynamic storage duration

该库提供全局分配和释放function的默认定义。 一些全局分配和释放function是可替换的。

C ++程序最多只能提供一个可替换分配或释放function的定义。 任何此类函数定义都将替换库中提供的默认版本。

以下分配和释放函数在程序的每个转换单元中的全局范围中隐式声明:

  • void* operator new(std::size_t);
  • void* operator new[](std::size_t);
  • void operator delete(void*);
  • void operator delete[](void*);

好。 挖出标准的旧工作草案(2011年2月28日转3242)。相关部分似乎是3.7.4 Dynamic storage duration18.6.1 Storage allocation and deallocation

简而言之,我想要的泛星系钩子似乎是全球新的和删除操作员本身。 如果尊重某些语义(在3.7.4.13.7.4.2 :基本上根据需要委托给new_handler ),则允许替换

 void* operator new(std::size_t); void* operator new[](std::size_t); void operator delete(void*); void operator delete[](void*); 

阻止整个C ++程序的默认内存管理。 我仍然找不到certificate@paxdiablo正确的部分,但我现在愿意和它一起运行。

您不必担心生成的Flex或Bison代码分配的内存; 他们自己照顾它。 其余的,只需使用newdelete 。 (并且Flex和Bison能够生成类似的C ++。一般来说,我发现通过一个简单的脚本运行输出,使用sed足以使它们的输出真正与C ++兼容。)