未定义行为与格式错误的 C++ 程序之间的区别 - The Old New Thing

主要观点:C++语言有“不要那样做”的两大类,即未定义行为(Undefined Behavior,UB)和格式不良程序(Ill-formed Program),二者有区别。
关键信息:

  • 未定义行为(UB):是运行时概念,程序做了语言规定不允许做的事,运行时行为未定义,标准允许程序做任何事,其影响可能回溯时间并使之前的操作无效,如执行死代码等,但避免触发 UB 的代码路径就安全,如在nervous函数中,当is_scaryfalse时避免了除以零的操作。
  • 格式不良程序(Ill-formed Program):分为普通格式不良程序和无需诊断的格式不良程序(IFNDR)。普通格式不良程序标准要求编译器报告错误,编译器通常拒绝生成可运行程序;IFNDR 虽格式不良但标准不要求编译器报告错误,编译器可选择沉默,这类情况难以被编译器检测,如两个翻译单元中内联函数定义不一致,即使程序未执行包含 IFNDR 的代码路径,结果也是未定义的,可能导致程序行为异常,如内存损坏等,常见来源是根据不同的预处理设置对类进行更改。
    重要细节:
  • nervous函数中,根据is_scary的值决定返回值,当is_scaryfalse时避免除以零的错误。
  • 在普通格式不良程序的示例中,const int size = 4;中尝试修改const变量size,编译器报告编译时错误。
  • 在 IFNDR 的示例中,两个cpp文件中内联函数magic定义不一致,导致程序结果未定义,即使get_value函数未被调用,结果也不确定。
  • common.h中,根据预处理设置不同,两个cpp文件对Widget类的定义存在差异,可能导致内存损坏等问题,Visual Studio 有相关命令行选项和#pragma detect_mismatch可帮助检测这类不匹配。
    作者信息:Raymond Chen 参与 Windows 发展 30 多年,2003 年创建 The Old New Thing 网站,该网站很受欢迎,还出版了同名书籍,偶尔在 Windows Dev Docs 推特账号上讲故事。
阅读 9
0 条评论