首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >reinterpret_cast bug还是UB?

reinterpret_cast bug还是UB?
EN

Stack Overflow用户
提问于 2018-09-17 18:48:52
回答 2查看 660关注 0票数 15

考虑以下代码:

代码语言:javascript
复制
#include <cstdint>
#include <algorithm>

std::uintptr_t minPointer(void *first, void *second) {
    const auto pair = std::minmax(
        reinterpret_cast<std::uintptr_t>(first),
        reinterpret_cast<std::uintptr_t>(second)
    );
    return pair.first;
}

以及GCC8与-O3在_上为minPointer生成的程序集

代码语言:javascript
复制
minPointer(void*, void*):
  mov rax, QWORD PTR [rsp-8]
  ret

它显然不执行代码创建者的意图。是这段代码引起了UB还是GCC(8)的错误?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-09-17 19:07:28

这是UB,但不是因为你可能认为的原因。

std::minmax()的相关签名是:

template<类T> std::pair minmax( const T& a,const T& b );

在本例中,pair是对uintptr_t const的一对引用。我们所指的实际对象在哪里?没错,他们是在最后一行上创造的临时人员,已经超出了范围!我们有悬空的推荐信。

如果你写:

代码语言:javascript
复制
return std::minmax(
    reinterpret_cast<std::uintptr_t>(first),
    reinterpret_cast<std::uintptr_t>(second)
).first;

然后,我们没有任何悬空引用,您可以看到gcc生成了适当的代码:

代码语言:javascript
复制
minPointer(void*, void*):
  cmp rsi, rdi
  mov rax, rdi
  cmovbe rax, rsi
  ret

或者,您可以显式地将pair类型指定为std::pair<std::uintptr_t, std::uintptr_t>。或者干脆完全避开这对和return std::min(...);

就语言细节而言,由于[expr.reinterpret.cast]/4,允许将指针转换为足够大的整数类型,并且保证std::uintptr_t足够大。所以一旦你解决了悬空的参考问题,你就没事了。

票数 22
EN

Stack Overflow用户

发布于 2018-09-17 19:06:42

reinterpret_cast有很好的定义。问题是const auto pairconst std::pair<const std::uintptr_t&, const std::uintptr_t&>,因为这是std::minmax返回的内容,所以您有悬空的引用。

你只需要去掉那些悬空的引用就可以让它发挥作用:

代码语言:javascript
复制
std::uintptr_t minPointer(void *first, void *second) {
    const std::pair<std::uintptr_t, std::uintptr_t> pair = std::minmax(
        reinterpret_cast<std::uintptr_t>(first),
        reinterpret_cast<std::uintptr_t>(second)
    );
    return pair.first;
}

螺栓连接

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52374048

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档