Fed*_*dor 9 c++ language-lawyer constexpr dangling-pointer c++17
在 C++17 中的常量表达式求值期间,编译器是否应考虑寻址有效对象的任何指针与在其生命周期结束后寻址对象的任何指针不相等?
例如:
constexpr auto f(int * x = nullptr) {
int c = 0;
auto p = &c;
if ( x == p )
throw "unexpected";
return p;
};
int main() {
static_assert( f( f() ) );
}
Run Code Online (Sandbox Code Playgroud)
这里函数的内部调用f()返回一个悬空指针,该指针被再次传递给f。我相信条件x == p一定是false因为xis 是一个悬空指针并且p是一个有效指针,在 Clang 中确实如此。但在 GCC 中,条件得到满足,并且由于 ,常量求值失败throw。演示: https: //gcc.godbolt.org/z/ehcMro17q
这是一种未定义的或实现定义的行为,还是其中一个编译器是错误的?
悬空指针与任何其他指针的比较结果是实现定义的:
\n\n\n当到达存储区域的持续时间结束时,表示该存储区域的任何部分的地址的所有指针的值将变为无效指针值。\n通过无效指针值间接并将无效指针值传递给释放函数具有未定义的行为。\n对无效指针值的任何其他使用都具有实现定义的行为。
\n
( [basic.stc]/4 ) (相等比较包含在 \xe2\x80\x9cother use\xe2\x80\x9d 中。)
\n正如注释中所指出的,即使比较操作数的左值到右值转换也会调用无效指针的实现定义行为([conv.lval]/3.3)。
\n不幸的是,我\xe2\x80\x99找不到任何要求对相等比较的操作数进行左值到右值转换的内容;[expr.eq]/2至多间接地暗示了这一点。
\n