破壳Ai

  • 编程入门
    • C语言
    • 数据结构及算法基础
  • 应用程序开发
    • C++
    • Windows API编程
    • opengl图形编程
  • 计算机科学与Web
    • Python
    • 编程语言学
    • 信息理论
    • 人工智能
  • 计算机原理
    • 汇编
    • 系统编程
    • 操作系统
    • 编译原理
    • 网络
  • 关于
    • 关于
    • 友链
    • 支持小站
    • 留言
忘记时间 专注当下
  1. 首页
  2. 应用程序开发
  3. C++
  4. 正文

到底该不该用 C++ 异常?

2021-09-25 335点热度 0人点赞 0条评论

争论不休的 C++ 异常

异常一直是 C++ 中争议较大的语言特性。是否应该在项目中使用或禁用异常,应该是 C++ 开发者中讨论得最激烈的话题了——其拥护者和反对者都表现出较强的态度。

在著名的 Google C++ Style Guide 中,关于异常的一节,明确禁用 C++ 异常:

We do not use C++ exceptions.

禁用异常的主要原因是 Google 的历史包袱太重了,代码库中有很多旧风格的 C++ 代码对异常不友好,根本没考虑异常,做不到异常安全。

On their face, the benefits of using exceptions outweigh the costs, especially in new projects. However, for existing code, the introduction of exceptions has implications on all dependent code. If exceptions can be propagated beyond a new project, it also becomes problematic to integrate the new project into existing exception-free code. Because most existing C++ code at Google is not prepared to deal with exceptions, it is comparatively difficult to adopt new code that generates exceptions.

LLVM Coding Standards 中也禁止使用异常:

In an effort to reduce code and executable size, LLVM does not use exceptions or RTTI...

不过,LLVM 在创立之初并没有历史包袱,禁用异常的原因是异常让最终的二进制文件大小增加了不少——异常产生的位置决定了需要如何做栈展开(stack unwinding),这些数据需要存储在表里——这就是异常导致二进制较大的主要原因。

也有一些支持使用 C++ 异常的编码指南,比如 Bjarne Stroustrup(C++ 之父) 和 Herb Sutter 维护的 CppCoreGuidelines 中就旗帜鲜明地支持使用异常。可以参考 CppCoreGuidelines 中关于错误处理的一节。

isocpp 网站上,也有一个 FAQ 专门解释为什么应该使用异常:Exceptions and Error Handling。

关于 C++ 异常的思考

异常的好处很明显:

  1. 异常不能被忽略,没有处理异常的进程会自动挂掉。这点让我想起了曾经有个同学因为错误码没处理,代码继续往下执行,结果酿成了一场悲剧。虽然 gcc 支持 __attribute__((warn_unused_result)) , C++17 开始也支持 [[nodiscard]] 属性,但是从实践中看来,这些功能的使用目前并不普及。
  2. 简化代码。异常减少对错误码的层层传递和检查,使得正常代码的结构看起来更清晰。每个错误码的处理都要写一堆 if xxx else yyy 确实很难受,也很干扰正常逻辑。
  3. 异常可以让构造函数更加方便地报错。

异常带来的问题也很多:

  1. 保证代码异常安全,这对开发者的挑战很大。
  2. 引入异常,也就引入了一个隐含的执行路径。很多时候,你根本不知道一个函数会不会抛出异常,可能抛出哪些异常。
  3. C++ 异常不带调用栈信息,当在外层捕获到下层自动传播来异常时,现场已经没了。这时候反而可能是手动向上层层传播的错误码+错误日志更有利于定位到真正的问题。
  4. 性能。虽然现在的编译器已经能够做到异常对 happy-path 几乎无性能影响。但是如果 bad-path 的频率较高,性能开销则不可能忽略不计。
  5. 由于需要 stack unwind,二进制的大小会比较大。

小结

错误码和异常是两种不同的错误处理风格,使用错误码或异常其实各有优劣。C++ 没有强制开发者只能使用其中一种,重要的是在团队和项目中保持统一。个人认为,在一般团队中,要用好异常还是有一定挑战的。

转载from https://zhuanlan.zhihu.com/p/315789294 of FOCUS

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: C FOCUS
最后更新:2021-09-25

kerbal

这个人很懒,什么都没留下

打赏 点赞
< 上一篇
下一篇 >

文章评论

取消回复

关注公众号
Donation

Yahaha,you found me!

文章目录
  • 争论不休的 C++ 异常
  • 关于 C++ 异常的思考
  • 小结

COPYRIGHT © 2019-2022 破壳AI. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

浙ICP备19036001号