【问题标题】:What alignment does HeapAlloc useHeapAlloc 使用什么对齐方式
【发布时间】:2011-02-17 20:27:57
【问题描述】:

我正在开发一个使用 Win32 的 HeapAlloc 的通用库

MSDN 没有提到 Win32 的 HeapAlloc 的对齐保证,但我确实需要知道它使用什么对齐,这样我才能避免过多的填充。

在我的机器(vista,x86)上,所有分配都以 8 个字节对齐。其他平台也是这样吗?

【问题讨论】:

  • 如果MSDN没有说,那么没有保证。即使你问 1000 个人,他们都确定在他们的机器上是 8 个字节,这也不能保证,你可能不应该依赖它。
  • 我同意上述说法。你可能想看看blogs.msdn.com/oldnewthing/archive/2007/12/27/6873648.aspx 看看它是否相关。
  • 我同意,没有任何保证,但我不是在这里要求保证:我要求的是经验。我相信微软永远不会将对齐减少到 8 个字节以下,因为双精度将不再可读。我只是想知道嵌入式平台也是如此。

标签: c++ c alignment heapalloc


【解决方案1】:

此处记录了 Amd64 堆对齐:

https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-160

...堆栈指针和 malloc 或 alloca 内存,16 字节对齐以提高性能。

【讨论】:

    【解决方案2】:

    HeapAlloc 函数并没有在 MSDN 页面中指定对齐保证,但我倾向于认为它应该具有与 GlobalAlloc 相同的保证,即保证返回 8 字节对齐的内存(尽管依赖于未记录的特性是邪恶的);毕竟,它明确表示 Global/LocalAlloc 只是 HeapAlloc 的包装器(尽管它们可能会丢弃前 n 个字节以获得对齐的内存 - 但我认为这不太可能)。

    如果您真的想确定,只需使用 GlobalAlloc,甚至是 VirtualAlloc,其粒度就是页面粒度,通常为 4 KB (IIRC),但在这种情况下,对于小型分配,您会浪费大量内存.

    顺便说一句,如果您使用 C++ new 运算符,则可以保证为您指定的类型正确对齐内存:这可能是要走的路。

    【讨论】:

      【解决方案3】:

      令人惊讶的是,Google 发现 evidence HeapAlloc 并不总是符合 SSE:

      HeapAlloc() 使所有对象总是 8 字节对齐,无论它们的大小是多少(但不是 16 字节对齐,对于 SSE)。

      这篇文章来自 2008 年中期,表明最近的 Windows XP 存在这个错误。

      另见http://support.microsoft.com/kb/286470

      Windows 堆管理器(所有版本)始终保证堆分配具有 8 字节对齐的起始地址(在 64 位平台上对齐为 16 字节)。

      【讨论】:

      • 是的,SSE 类型生活在一种阴影中,分配函数很少尊重它们的对齐方式。我不确定为什么,但在 Windows 和 Linux 上似乎都是这种情况。默认情况下,您不会得到比 8 个字节更好的对齐保证。
      • @jalf:奇怪!我记得在 1999 年推出 AltiVec 时,Apple 立即重新指定了它们的分配函数 NewPtrNewHandle 用于 16 字节对齐。这不像你那样破坏旧软件!
      【解决方案4】:

      对齐将使得返回的地址可以转换为任何类型的指针。否则您将无法在应用程序中使用内存。

      【讨论】:

      • 如果我理解正确你的答案,返回的地址可以转换为任何类型的指针这一事实与分配的内存的对齐方式无关。
      • @Matteo:它是相关的。如果它没有与类型 T 对齐,那么对 T* 的强制转换将是无效的(它会编译,但不能保证工作)。因此,因为它可以转换为任何类型,所以它必须严格对齐以适用于任何类型。
      • 好的,我理解你的答案,所以我之前说的不适用;仍然,操作系统不能保证它与 any 类型对齐,否则只有一个 NULL 指针就可以了 :) 。可能保证它适用于编写分配器的人已知的需要对齐的最大类型(或编写分配器的人愿意直接支持的需要对齐的最大类型)。
      • 不幸的是,这个保证是无效的:在 vista32 上,对齐是 8 个字节,适用于双精度和长整数,但不适用于需要 16 个字节的 SSE 内在类型对齐,所以需要手动对齐。
      猜你喜欢
      • 1970-01-01
      • 2010-10-26
      • 2021-04-13
      • 2021-10-24
      • 1970-01-01
      • 1970-01-01
      • 2016-04-15
      • 2021-01-11
      相关资源
      最近更新 更多