bar*_*top 15 c++ undefined-behavior language-lawyer reinterpret-cast
考虑以下代码:
#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;
}
Run Code Online (Sandbox Code Playgroud)
并且所产生的组件通过与-O3 GCC8上
https://godbolt.org/z/qWJuV_为minPointer:
minPointer(void*, void*):
mov rax, QWORD PTR [rsp-8]
ret
Run Code Online (Sandbox Code Playgroud)
这显然不符合代码创建者的意图.这个代码是导致某些UB还是GCC(8)错误?
Bar*_*rry 22
这是UB,但不是你想的原因.
相关签名std::minmax()是:
Run Code Online (Sandbox Code Playgroud)template< class T > std::pair<const T&,const T&> minmax( const T& a, const T& b );
在这种情况下,您pair是一对引用uintptr_t const.我们引用的实际对象在哪里?这是对的,他们是在最后一行创建的临时表已经超出了范围!我们有悬挂参考.
如果你写道:
return std::minmax(
reinterpret_cast<std::uintptr_t>(first),
reinterpret_cast<std::uintptr_t>(second)
).first;
Run Code Online (Sandbox Code Playgroud)
然后我们没有任何悬空引用,你可以看到gcc生成适当的代码:
minPointer(void*, void*):
cmp rsi, rdi
mov rax, rdi
cmovbe rax, rsi
ret
Run Code Online (Sandbox Code Playgroud)
或者,您可以明确指定pairas 的类型std::pair<std::uintptr_t, std::uintptr_t>.或者只是完全回避这对return std::min(...);.
就语言细节而言,由于[expr.reinterpret.cast]/4,您可以将指针转换为足够大的整数类型,并且std::uintptr_t保证足够大.所以一旦你解决悬空参考问题,你就没事了.
Jus*_*tin 13
这reinterpret_cast是明确的定义.问题是,返回的类型const auto pair是const std::pair<const std::uintptr_t&, const std::uintptr_t&>什么std::minmax,所以你有悬挂引用.
你只需要摆脱悬挂的引用就可以了:
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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
460 次 |
| 最近记录: |