C++ 自(vs2012/2010/2013)以来,msvcrt是否使用不同的堆进行分配

C++ 自(vs2012/2010/2013)以来,msvcrt是否使用不同的堆进行分配,c++,msvcrt,C++,Msvcrt,我在一段时间前就读到了这方面的内容,但我无法在msdn或web上的任何其他地方找到对crt的更改 我认为msvcrt在VS2012的VC++版本中已经改变,不再使用私有堆进行分配,而是使用进程堆 Afaik的目标是在多个lib中分配内存,这些lib与crt静态链接,随后在另一个lib中释放内存 这是我观点的一个重大变化,我想知道为什么我找不到任何提到它的文件。 要么这样,要么是我编造的(我怀疑这一点,因为我不久前与同事讨论过这个话题)这是正确的。这一变化是在VS2012年做出的,似乎是未来的行为

我在一段时间前就读到了这方面的内容,但我无法在msdn或web上的任何其他地方找到对crt的更改

我认为msvcrt在VS2012的VC++版本中已经改变,不再使用
私有堆
进行分配,而是使用
进程堆

Afaik的目标是在多个lib中分配内存,这些lib与crt静态链接,随后在另一个lib中释放内存

这是我观点的一个重大变化,我想知道为什么我找不到任何提到它的文件。
要么这样,要么是我编造的(我怀疑这一点,因为我不久前与同事讨论过这个话题)

这是正确的。这一变化是在VS2012年做出的,似乎是未来的行为。您可以在CRT的源代码中看到相关代码,请在vc/CRT/src/heapinit.c源代码文件中找到:

int __cdecl _heap_init (void)
{
        if ( (_crtheap = GetProcessHeap()) == NULL )
            return 0;

        return 1;
}
以前的版本在这里使用了HeapCreate(),也使用了VS5和VS6遗留黑客。这一点没有得到充分的宣传,因此其背后的确切原因也不太清楚。VS2012的一个重要细节是,它最初不支持XP。它放弃了显式启用低碎片堆的要求。LFH在Vista及更高版本上自动启用,因此默认进程堆已经很好了

使用默认进程堆的一个非常重要的优点是,它解决了DLL拥有自己的CRT副本,从而使用自己的分配器的非常棘手的问题。传统上,当一个DLL需要释放另一个DLL分配的内存时,这种方法会非常糟糕。再也没有这样的问题了,只要重新构建DLL以针对更高版本的CRT,它们现在就会自动使用完全相同的堆,因此跨模块边界传递指针是安全的

一些担忧也是正确的。我不清楚更新1中发生了什么,它带来了XP支持。假设CRT源代码是准确的(看起来是准确的),那么您的程序很有可能在XP上没有启用LFH的情况下运行


还有一个可能的安全问题,winapi也使用默认进程堆。因此,从技术上讲,恶意软件现在有可能劫持代码中的缓冲区溢出错误并到达winapi缓冲区。如果您以前对代码进行过安全分析和/或模糊测试,那么您应该重做。我假设微软非常依赖他们的安全CRT实现来避免安全问题,但这是一个盲目的猜测。希望詹姆斯·麦克内利斯(James McNellis)能够提供更深入的见解。

CRT源代码是否仍然随VS一起提供?我的不方便检查,但我认为它仍然有用。如果是这样的话,就很难打败这个引用。因为它现在使用GetProcessHeap,这是否意味着现在支持将同一VS版本的静态和动态CRT混合使用?@paulm,afaik这确实是个暗示。很好的解释,感谢您对XP和安全性的额外提示。现在已经确认了,我集中精力查找msdn文章。我很确定msdn没有在任何地方提到这一点。我发现一篇针对VS2012的文章似乎完全忽略了crt上进程堆的含义:因为它仍然指出跨越dll边界仍然是一个问题。这让我很困惑。是的,它很古老。注意它是如何谈论版本4.1和5.0的,这是三个狗的生命。关于跨模块传递CRT状态(如区域设置、错误号等)的担忧仍然有效。@Samuel:这取决于CRT向Windows堆添加了多少管理。在调试代码中,它的泄漏报告功能和边界检查非常重要;在发布模式下,分配似乎只是转发给HeapAlloc。不过,在模块上始终使用相同的共享crt库还是更好的。