gpt4 book ai didi

c++ - 为什么 GCC 在这里优化分配?

转载 作者:太空狗 更新时间:2023-10-29 21:10:32 29 4
gpt4 key购买 nike

我有一个类 offset_ptr,它的工作方式类似于指针,但将它指向的内存地址存储为它自己的地址 this 的偏移量。这是一个删除了不需要证明问题的所有内容的版本:

template <typename T>
struct offset_ptr {
using offset_t = int64_t;
static constexpr auto const NULLPTR_OFFSET =
std::numeric_limits<offset_t>::max();

offset_ptr(T const* p)
: offset_{p == nullptr ? NULLPTR_OFFSET
: static_cast<offset_t>(
reinterpret_cast<uint8_t const*>(p) -
reinterpret_cast<uint8_t const*>(this))} {}

T* get() {
return
offset_ == NULLPTR_OFFSET
? nullptr
: reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(this) + offset_);
}

offset_t offset_;
};

此代码不适用于 GCC -O2-O3:

int* get() {
offset_ptr<int> ptr = static_cast<int*>(malloc(sizeof(int)));
auto p = ptr.get();
*p = 110; // WOW - please do not optimize me away :-(
return p;
}

(为了简单起见,有意省略了内存管理和错误检查!)

这在生成的程序集中也可见: https://godbolt.org/z/PfZEJM

只是缺少作业。

如上面的 Godbolt Compiler Explorer 链接所示,它在以下情况下工作

  • 分配的值直接在函数本身中使用
  • offset_ptr 位于堆上,而不是堆栈上
  • 根本没有使用offset_ptr

适用于:

  • Clang(有和没有优化)
  • MSVC(调试和 Release模式)
  • GCC(当前和旧版本)-O0-O1(但 NOT -O2-O3)

GCC 和 Clang Address 以及 UB sanitizer 构建在执行时没有显示任何问题(除了内存泄漏)。

有人可以指出 C++ 标准文档中的一个部分说这段代码中有 UB(这可能是 GCC 积极优化赋值的原因)?还是 GCC 中的错误?

编辑:删除 offset_ptr 中的 nullptr 检查有助于 ( https://godbolt.org/z/5HjcLY )。但我需要那些空检查。

最佳答案

[expr.add]p5 :

When two pointer expressions P and Q are subtracted, the type of the result is an implementation-defined signed integral type; [...]

  • If P and Q both evaluate to null pointer values, the result is 0.
  • Otherwise, if P and Q point to, respectively, elements x[i] and x[j] of the same array object x, the expression P - Q has the value i-j.
  • Otherwise, the behavior is undefined.

成员初始值设定项列表中的减法返回到第三点,因此您有 UB。

如果您删除 nullptr 检查它“有效”,因为 gcc 无法证明第一个条件不会发生。

关于c++ - 为什么 GCC 在这里优化分配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53791584/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com