【问题标题】:On Memory Allocation and C++关于内存分配和 C++
【发布时间】:2011-03-03 05:22:35
【问题描述】:

我引用 MSDN http://msdn.microsoft.com/en-us/library/aa366533(VS.85).aspx:

malloc 函数具有 运行时的缺点 依赖。新运营商拥有 编译器的缺点 依赖和语言依赖。

现在问题来了:

a) malloc 依赖于运行时是什么意思?什么样的动态内存分配函数可以独立于运行时?这种说法听起来真的很奇怪。

b) new 依赖于语言吗?当然应该是对的? HeapAlloc、LocalAlloc 等语言是否独立?

c) 从纯粹的性能角度来看,MSVC 提供的例程是否更可取?

阿潘

【问题讨论】:

  • 用 cmets 评论他的回答,而不是在这里。
  • 对我来说真的很晦涩;当然,在运行时完成的每个“真实”内存请求都是依赖于运行时的。 new 运算符当然是依赖于语言的......但是依赖于编译器?!如果我们谈论的是 C++,它是标准化的,我希望 new 的行为不依赖于编译器;它如何实现其目的当然取决于编译器(但这也是一个无趣的细节),也取决于系统......(毕竟是 malloc)......

标签: c++ visual-studio visual-c++


【解决方案1】:

使用 DLL 时会出现 malloc 和 new 的问题。根据构建选项,DLL 可能有自己的 CRT 副本。这使得它使用自己的堆来分配内存,与 EXE 使用的堆不同。当内存由一个模块分配并由另一个模块释放时,这会导致失败。使用 STL 时非常常见。

解决此问题的一种方法是使用 /MD 选项编译代码。这会强制使用 CRT 的共享副本,该副本存储在它自己的 DLL 中。问题解决了,现在只有一个分配器,使用一个堆。

COM 也会出现这个问题,它允许不同的语言进行互操作。他们当然不会共享分配器,因为这些语言有不同的运行时支持库。按照约定,COM 代码必须使用由 COM 运行时支持提供的单个分配器 CoTaskMemAlloc()。

注意 HeapAlloc() 不能解决这个问题。它需要一个堆句柄,由 HeapCreate() 返回。不同的模块必须共享该句柄以避免麻烦。


更新:在 VS2012 中解决,CRT 现在从共享堆分配,默认进程堆(GetProcessHeap 函数)。

【讨论】:

    【解决方案2】:

    哇,这是一个奇怪的声明,出现在文档中没有附带解释。会不会是从引入 C++ 开始的延迟?我只能猜测您的问题的答案:

    a) 也许他们的意思是将其与链接/加载时间分配进行对比,例如全局变量、常量和static 数据。或者他们的意思是将其与堆栈分配进行对比,例如alloca 系列。

    b) 他们可能会注意到您不应该使用 C++ new 分配内存,然后将该内存的所有权传递给可能free() 的库例程。所以从这个意义上说,分配的结果是特定于语言的。

    c) 使用 C++ newdelete。您必须假设 MSVC 运行时中的底层 C++ 分配器与 C 风格的系统调用一样快,如果不完全相同的话。请记住,newdelete 所做的不仅仅是分配和释放内存。它们不能完全替换为mallocfree 或其他C 风格的分配器。

    【讨论】:

      【解决方案3】:

      a) 在这种情况下,我认为他们将“运行时库”省略为“运行时”。换句话说,它取决于您的 C 库中的实现。

      b) 实际上 new 是 C++ 特有的。 HeapAlloc 等在技术上可用于 C 和 C++。

      c) 它们不能用于创建 C++ 对象,因为它们不会调用构造函数,所以这一点没有实际意义。在 C++ 中,您应该使用 new 和 delete。

      【讨论】:

      • 如果你想使用便携式分配器,请重新定义全局operator new
      • 更不用说 HeapAlloc 和朋友也是特定于 Windows 的 - 如果你使用这些,你可以使你的代码可移植的唯一方法是为其他平台制作你自己的 HeapAlloc...何必什么时候可以只使用 malloc/free 或 new/delete?
      【解决方案4】:

      a) 这意味着 malloc 的行为取决于您编译的 C 运行时版本。

      b) HeapAlloc 和 LocalAlloc 是 Win32 API 函数。它们确实是运行时和语言独立的。

      c) 如果不知道运行时例程是如何实现的,这是不可能回答的。我怀疑他们的表现是可比的。无论如何,如果您使用 new 运算符,那么您始终可以在必要时选择在以后覆盖它。请记住,过早的优化是万恶之源。 ;)

      最后一点:LocalAlloc 和 GlobalAlloc 很慢。你不应该使用它们,除非被一个笨拙的旧 Win32 API 强制使用。

      【讨论】:

        猜你喜欢
        • 2010-12-10
        • 2014-12-11
        • 2021-08-27
        • 1970-01-01
        • 1970-01-01
        • 2019-07-17
        • 1970-01-01
        • 2012-09-30
        • 2015-02-11
        相关资源
        最近更新 更多