reinterpret_cast错误还是UB? [英] reinterpret_cast bug or UB?
问题描述
考虑以下代码:
#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上生成的程序集
https://godbolt.org/z/qWJuV_ for minPointer
:
and the assembly generated by GCC8 with -O3 on
https://godbolt.org/z/qWJuV_ for minPointer
:
minPointer(void*, void*):
mov rax, QWORD PTR [rsp-8]
ret
显然不符合代码创建者的意图.这段代码会导致某些UB还是GCC(8)错误?
which clearly does not do what is intended by the code creator. Is this code causing some UB or is it GCC(8) bug?
推荐答案
这是UB,但并非出于您可能会想到的原因.
This is UB, but not for the reason you might think.
std::minmax()
的相关签名是:
The relevant signature of std::minmax()
is:
template< class T >
std::pair<const T&,const T&> minmax( const T& a, const T& b );
在这种情况下,您的pair
是对uintptr_t const
的一对引用.我们要引用的实际对象在哪里?是的,它们是在最后一行创建的临时文件,已经超出范围!我们有悬而未决的参考文献.
In this case, your pair
is a pair of references to uintptr_t const
. Where are the actual objects we're referencing? That's right, they were temporaries created on the last line that have already gone out of scope! We have dangling references.
如果您写过:
return std::minmax(
reinterpret_cast<std::uintptr_t>(first),
reinterpret_cast<std::uintptr_t>(second)
).first;
然后我们没有任何悬挂的引用,您会看到gcc生成了适当的代码:
then we don't have any dangling references and you can see that gcc generates appropriate code:
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(...);
.
Alternatively, you could explicitly specify the type of pair
as std::pair<std::uintptr_t, std::uintptr_t>
. Or just sidestep the pair entirely and return std::min(...);
.
就具体语言而言,由于 [expr.reinterpret.cast]/4 ,并且保证std::uintptr_t
足够大.因此,一旦解决了悬而未决的参考问题,就可以了.
As far as language specifics, you are allowed to convert a pointer to a large enough integral type due to [expr.reinterpret.cast]/4, and std::uintptr_t
is guaranteed to be large enough. So once you fix the dangling reference issue, you're fine.
这篇关于reinterpret_cast错误还是UB?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!