有关内存对齐的其他问题

时间:2019-02-09 21:23:24

标签: c++ memory-alignment

以前在内存对齐方面有一些很好的答案,但是我觉得还没有完全回答一些问题。

例如:

What is data alignment? Why and when should I be worried when typecasting pointers in C?

What is aligned memory allocation?

我有一个示例程序:

#include <iostream>
#include <vector>
#include <cstring>

int32_t cast_1(int offset) {
  std::vector<char> x = {1,2,3,4,5};
  return reinterpret_cast<int32_t*>(x.data()+offset)[0];
}

int32_t cast_2(int offset) {
  std::vector<char> x = {1,2,3,4,5};
  int32_t y;
  std::memcpy(reinterpret_cast<char*>(&y), x.data() + offset, 4);
  return y;
}

int main() {
  std::cout << cast_1(1) << std::endl;
  std::cout << cast_2(1) << std::endl;
  return 0;
}

cast_1函数输出ubsan对齐错误(如预期),但cast_2不会。但是,cast_2对我来说可读性差得多(需要3行)。 cast_1的意图非常清晰,即使它是UB。

问题:

1)当意图很明确时,为什么cast_1 UB?我了解对齐可能存在性能问题。

2)cast_2是固定cast_1 UB的正确方法吗?

2 个答案:

答案 0 :(得分:3)

  

1)为什么cast_1 UB?

因为语言规则这么说。实际上有多个规则。

  1. 您访问对象的偏移量不符合int32_t的对齐要求(对齐要求为1的系统除外)。如果不符合类型的对齐要求,则无法创建任何对象。

  2. char指针不能别名为int32_t

  

2)cast_2是固定cast_1 UB的正确方法吗?

cast_2具有明确的行为。该函数中的reinterpret_cast是多余的,并且使用魔术常数(使用sizeof)是很不好的。

答案 1 :(得分:1)

第一个问题是WRT,对于编译器来说,为您处理这个问题将是微不足道的。要做的就是对程序中的所有其他非字符加载进行模拟

精确地编写了对齐规则,因此编译器可以生成在许多平台上都能很好地执行代码,在这些平台上,对齐的内存访问是一种快速的本机操作,而对齐错误的访问与memcpy等效。除了可以证明对齐的地方之外,编译器还必须以缓慢且安全的方式处理每次加载。