这是一篇关于程序员对空指针常见误解的文章,主要内容如下:
- 基本信息:发布于 2025 年 1 月 30 日,在 Hacker News 和 Reddit 上有讨论,2 月 1 日添加内容,假设读者具备相关基础知识,否则阅读可能有害。
- 空指针表面简单却危险:编译器优化、直观但错误的简化以及平台特定的特性导致做出错误假设的几率增加,从而引发漏洞和错误。
常见误解及案例:
- 误 1:解引用空指针立即崩溃程序:高级语言和库可处理错误,在 Windows 安装向量异常处理程序,在类 Unix 平台安装信号处理程序。
- 误 2:解引用空指针最终导致程序终止:向量异常和信号处理程序可恢复程序,Go 和 Java 中可捕获相关错误。
- 误 3:解引用空指针总是导致信号、异常或被硬件拒绝:在某些平台上,解引用空指针不一定导致这些情况,如虚拟内存出现前、某些嵌入式平台和 WebAssembly 中。
- 误 4:解引用空指针总是触发“未定义行为”:标准中说触发未定义行为,但随着时间推移其含义发生了变化,过去在多数平台上解引用空指针与解引用地址 0 的指针行为相同。
- 误 5:空指针地址为 0:C 标准不要求空指针地址为 0,某些架构和 C 解释器使用非零空指针,Rust 等现代语言通常不支持这种情况。
- 误 6:现代平台上空指针地址为 0:在某些 GPU 架构上,0 指向可访问内存,空指针可能表示为-1。
- 误 7:(void)0 是空指针,(void)x(x = 0)也一定是空指针:x 不是常量表达式,标准不要求其产生空指针,运行时整数到指针的转换通常是无操作的。
- 误 8:在空指针地址为 0 的平台上,C 对象可能不放置在地址 0:指针到对象与空指针即使地址相同行为也不同,对象可放置在地址 0,但指针到对象与 NULL 不同。
- 误 9:在空指针地址为 0 的平台上,(void*)x(x = 0)与 NULL 比较相等:C 中指针到对象与 NULL 比较不等,证明来源会影响程序执行,Rust 不允许对象放置在地址 0。
- 误 10:在空指针地址为 0 的平台上,空指针存储为零:指针的地址和位表示不一定相等,如分段寻址、指针认证等情况,在 CHERI 中更复杂。
应对方法:
- 不要试图超越编译器或运行时,将 C 视为高级语言,避免一些可能导致非便携式代码的操作,如 memset、不必要的指针转换等。
- 当有疑问时,查阅 C 标准、编译器文档或咨询编译器开发者,必要时记录假设,以便用户理解软件的限制和开发者移植应用。
总之,了解空指针的各种特性和避免常见误解对于编写可移植和安全的 C 代码非常重要。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。