【问题标题】:stuck on understanding memory alignment坚持理解内存对齐
【发布时间】:2019-05-18 03:09:34
【问题描述】:

The code分配内存保存width * height的图像如下:

  const size_t alignment = 64;
  size_t space = width * height * bytes_per_pixel + alignment;
  rawdata = new unsigned char[space];
  //typedef unsigned long int uintptr_t
  uintptr_t ptr = reinterpret_cast<uintptr_t>(rawdata); 
  uintptr_t aligned = (ptr - 1u + alignment) & -alignment; 
  data = reinterpret_cast<unsigned char *>(aligned);

似乎在rawdata(即最初分配的内存)上执行了 64 字节对齐,从而生成了data 指向的对齐内存。但是,让我感到困惑的是这行:

uintptr_t aligned = (ptr - 1u + alignment) & -alignment

谁能帮帮我?

【问题讨论】:

  • 请注意,这是一种过时的获取过度对齐内存的方法。自 C++17 起,C++ 支持请求此类内存。之前,你可以在POSIX系统上使用一些非标准的函数,比如posix_memalign

标签: c++ memory-management memory-alignment


【解决方案1】:

该计算确保地址与给定的数量对齐(必须是 2 的幂)。这意味着当对齐为2^n 时,最低的n 位必须为零。

让我们用二进制来做。假设我们得到一个随机指针对齐 16 字节,而我们希望它对齐 64 字节并计算。 (这假设了二进制补码,顺便说一下,这并不能保证,但这是事实上的标准):

address = ...1101010000
address - 1 -> ...1101001111
address + 64 -> ...1110001111
-alignment -> ...1111000000
address & -alignment -> ...1110000000

因此实际上它找到了可以被对齐整除的最小值,因为-alignment 在对齐点下方的所有位都为零。它还通过添加alignment-1 来确保它大于原始指针,这是-alignment 作为位的否定,即所有高位为零,但低位为1。

如果地址已经对齐怎么办?然后计算结果是原始指针,因为它的最低位为零,您将所有最低位设为 1,然后将它们与它们分开。

【讨论】:

  • @Amadeus 在代码中声明uintptr_ttypedefd 为unsigned long int,所以没有指针运算,只有整数运算。
  • @Sami Kuhmonen 感谢您的详细说明。新对齐的address 至少比原始未对齐的address 大63,这就解释了需要额外的内存(就像size_t space = width * height * bytes_per_pixel + alignment 一样),那么size_t space = width * height * bytes_per_pixel + alignment-1 怎么样? :)
  • @Finley 是的,我打算添加它,但决定不添加 :) 63 个字节足以容纳额外的空间,因为它永远不会超过这个。
猜你喜欢
  • 2020-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-15
  • 2019-04-11
  • 1970-01-01
  • 2012-02-23
相关资源
最近更新 更多