g++与clang++-12编译同一段C++代码行为不同,哪一个是正确的?
问题结论
两款编译器的行为均符合C++标准要求,该代码本身存在触发未定义行为的错误,标准对未定义场景的程序表现没有强制约束。
代码问题分析
- 函数
temp_func返回值类型为const int&,执行return 3时,会首先生成一个临时int对象存储字面量3,再将返回的const引用绑定到这个临时对象上。 - C++标准明确规定了临时对象生命周期延长的适用边界:仅当const左值引用/右值引用直接在当前作用域绑定到临时对象时,临时对象的生命周期才会延长到和引用一致。而函数返回语句中绑定到返回值的临时对象,生命周期仅持续到函数执行结束、栈帧销毁为止,不会随返回的引用延长到函数外部。
- 因此
main函数中读取temp_func()返回值的操作,本质是访问已经被释放的栈内存,属于典型的悬垂引用访问,触发C++标准定义的未定义行为。
编译器行为差异的原因
对于未定义行为,C++标准不做任何输出限制,编译器可以自由选择处理逻辑:
- g++编译版本运行触发段错误,是因为函数栈帧销毁后对应内存页被标记为不可访问,读取该地址直接触发操作系统的内存访问错误。
- clang++-12编译版本输出3,是因为对应栈内存销毁后还未被其他操作覆盖,仍保留了原值3,读取时刚好拿到了旧数据。
两种处理逻辑都完全符合C++标准的规定。
内容的提问来源于stack exchange,提问作者Arnab De
相关产品推荐
相关产品推荐

