【问题标题】:Is the pointer passed to placement new a non-UB pointer to its object representation?传递给放置 new 的指针是否是指向其对象表示的非 UB 指针?
【发布时间】:2020-05-31 06:31:42
【问题描述】:
struct foo {
   int a;
   int b;
};

std::array<char, sizeof(foo)> buffer;
foo a {1, 2};
foo* b {new (buffer.data()) foo};
std::memcpy(buffer.data(), &a, sizeof(foo));
a == *b; // the important part

我知道放置 new 使 b 的字段的值不确定,但是后续的 memcpy 是否通过指向缓冲区的指针传递给 new,然后将 b 转换为 @987654325 的副本@?还是有UB,因为我不是通过new返回的指针memcpy-ing?

cppreference 对我来说有点太迟钝了,在这种情况下,我无法确定它是否已定义。

编辑:假设 buffer 正确对齐以使新的展示位置有意义

【问题讨论】:

  • new (buffer.data()) foo 很可能是 UB,因为 buffer.data() 很可能未与 alignof(foo) 对齐。使用std::aligned_storage..
  • std::memcpy(buffer.data(), &amp;a, sizeof(foo)); 是 UB 有两个原因:buffer.data() 指向其生命周期之外的对象,因此 memcpy 将访问生命周期之外的对象。而且既然已经是UB了,第二个原因就不用写了。

标签: c++ language-lawyer


【解决方案1】:

新位置

如果提供了placement_params,它们将被传递给分配 用作附加参数。这种分配函数是已知的 作为“放置新”,在标准分配函数 void* 之后 运算符 new(std::size_t, void*),它只返回它的第二个 论据不变。这用于构造已分配的对象 存储:

以上来自cppreference,所以你在memcpy之后是正确的'b'的内存内容与'a'相同

来源:https://en.cppreference.com/w/cpp/language/new

【讨论】:

  • 所以根据类型别名规则,buffer.data()b 的允许别名(因为它是char*)。放置new 是否保证生成与传递的指针具有相同“地址”的指针(即它们实际上是彼此的别名)?
  • 从我看来,第二个总是可以保证的语言。虽然,取消引用 buffer.data() 不会产生 foo 类型。该问题的原始 cmets 提出了一个有效问题,您必须确保 buffer.data() 的生命周期与您的期望相匹配。
猜你喜欢
  • 2018-09-03
  • 1970-01-01
  • 2021-12-03
  • 2014-03-31
  • 2018-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-02
相关资源
最近更新 更多