VS2017编译C++虚函数代码异常:是编译器Bug还是未定义行为?
编译器Bug还是未定义行为?
以下C++代码在VS2017中使用cl.exe /GL /O1(全程序优化+优化尺寸)编译时出现异常:
#include <cstdio> struct Parent { virtual const char *name() const { return name2(); } virtual const char *name2() const { return "Parent"; } }; struct Child : public Parent { virtual const char *name2() const { return "Child"; } }; int main() { Parent parent{}; static constexpr Child child{}; printf("%s\n", child.name()); }
- 当存在
Parent parent{};语句时,程序输出Parent - 移除该语句则输出
Child
该问题在现代Visual Studio版本及g++中已修复。用户预期输出Child,因为Parent::name应调用Child::name2,现需确认此情况属于编译器Bug还是未定义行为,以及后续能否依赖正常运行结果。
这是VS2017旧版本编译器的Bug,不属于C++标准定义的未定义行为。
从C++标准角度分析:
child是Child类型的常量对象,调用name()时,虽然name()是基类Parent的成员函数,但虚函数的动态绑定规则明确要求,必须根据对象的实际类型(Child)调用对应的name2()版本——也就是Child::name2(),所以预期输出Child完全符合标准。- 代码中没有任何违反C++标准的写法,
Parent parent{};只是一个无关的局部对象声明,不应该影响child对象的虚函数调用逻辑。
VS2017在开启/GL(全程序优化)时出现的错误,是编译器优化阶段的逻辑漏洞,误将child对象的虚函数调用静态绑定到了Parent::name2(),而parent对象的存在触发了这个错误逻辑。现代VS版本和g++无此问题,说明厂商已经修复了该Bug。
后续可以放心依赖正常运行结果,只要使用未存在该Bug的编译器版本即可。
内容的提问来源于stack exchange,提问作者fjjrl wlkejrlwej
相关产品推荐
相关产品推荐

