文章摘要
这篇文章指出,C和C++语言中存在大量未定义行为,即使经验丰富的程序员也难以完全避免。作者以30年编程经验强调,这些诞生于上世纪的语言已不适应当今环境,其安全隐患可能违反现代法规。未定义行为的范围远超常人认知,包括内存访问等基本操作都可能触发。
文章总结
标题:C语言中的一切行为都可能未定义
来源:https://blog.habets.se/2026/05/Everything-in-C-is-undefined-behavior.html 发布时间:2026年5月19日
核心内容:
- C/C++的普遍性问题
- 作者指出,即使是最资深的C程序员编写的代码,也难免存在未定义行为(UB)
- 经过30年C/C++开发经验,作者认为在2026年的今天,这些诞生于1972年(C)和1985年(C++)的语言已不合时宜
- 未定义行为的本质
- 常见误解:认为关闭优化选项就能避免UB的影响
- 实际含义:编译器可以假设代码完全合法,导致人类可读的意图在编译过程中无法表达
- 硬件层面也存在类似问题,执行结果无法保证始终符合预期
- 典型未定义行为案例 (1) 内存对齐问题
- 访问未对齐指针是UB,不同架构表现各异(Alpha可能内核修复,SPARC崩溃,x86通常正常)
- 原子操作在未对齐时同样存在UB
(2) 指针转换问题 - 创建未对齐指针本身就已构成UB - 编译器可能利用指针低位实现垃圾回收或安全标记
(3) 字符处理函数 - 将signed char直接传递给isxdigit()可能导致越界内存访问 - 极端情况下可能触发硬件操作(如启动电机)
(4) 浮点数转换 - 超出范围的float转int是UB - 正确实现需要复杂的边界检查
(5) 零地址对象 - 内核/嵌入式开发中无法标准合规地使用零地址对象 - memset清零结构体不能保证指针成员变为NULL
(6) 可变参数类型 - printf格式说明符与参数类型不匹配是UB - 系统调用参数类型错误也是常见问题
- 解决方案建议
- 建议使用AI工具辅助检测UB(作者测试发现LLM能有效识别OpenBSD等成熟项目中的UB)
- 指出完全重写现有代码库不现实,但需要系统性解决方案
- 强调这项工作需要专家参与,不能完全交由初级开发者
补充说明: - C23标准中"undefined"出现283次 - 整数提升规则极其复杂,几乎无人能快速准确判断 - 除零等常见UB可能带来安全隐患
(注:原文中部分历史典故、个人经历等非技术性内容已酌情删减)
评论总结
以下是评论内容的总结:
关于类型转换的争议
- dmitrygr认为将uint8t*转换为int*是安全的,因为uint8t本质上是unsigned char,符合C标准。
引用:"if you have uint8t, then it is 'unsigned char'"
"the cast itself is not [UB], since uint8t is ~ char" - liamd1988建议避免使用int,坚持使用char。
引用:"keep using char* not mess with int*"
- dmitrygr认为将uint8t*转换为int*是安全的,因为uint8t本质上是unsigned char,符合C标准。
对未定义行为(UB)的理解分歧
- veltas认为编译器对UB的解释过于法律化,违背了标准初衷。
引用:"compiler writers apply overly legalistic interpretation"
"the consequence...should be somewhat bounded" - bestouff指出UB的真正危险在于编译器可能产生意外优化。
引用:"the compiler...is allowed to translate that to anything"
"removing big chunks of code" - raluk将UB分为标准明确定义和未提及两类。
引用:"two kinds of undefined behaviour"
- veltas认为编译器对UB的解释过于法律化,违背了标准初衷。
关于现代C++的讨论
- stackghost强调现代C++与C的差异,提倡使用安全特性。
引用:"modern C++ is very different than C"
"using RAII with smart pointers" - debugnik批评文章借UB话题推销LLM编程。
引用:"a veil for pushing LLM coding"
- stackghost强调现代C++与C的差异,提倡使用安全特性。
关于LLM与UB的关系
- __0x01认为LLM生成的代码仍需要专家审核。
引用:"LLM generated code will eventually contain UB" - logicchains将UB概念类比LLM编程中的未明确规范部分。
引用:"Anything you don't explicitly specify is undefined behavior" - jraph讽刺性地评论LLM被过度推崇。
引用:"Yet another push to use LLMs"
- __0x01认为LLM生成的代码仍需要专家审核。
其他观点
- greysphere认为文章夸大了UB示例的实际影响。
引用:"examples aren't really undefined behavior" - quelsolaar用幽默方式描述学习UB的五个阶段。
引用:"The 5 stages of learning about UB" - momo26分享调试C代码的困难体验。
引用:"Debugging in C is soooo hard"
- greysphere认为文章夸大了UB示例的实际影响。
总结显示评论主要围绕UB的技术细节、编译器行为、现代C++实践以及LLM在编程中的角色展开讨论,观点呈现多样化。