正在C++;坏习惯? 我倾向于在C++代码中添加大量断言,以便在不影响发布版本性能的情况下更容易调试。现在,Asjt>/Cord>是一个纯C++宏,它没有C++机制,

正在C++;坏习惯? 我倾向于在C++代码中添加大量断言,以便在不影响发布版本性能的情况下更容易调试。现在,Asjt>/Cord>是一个纯C++宏,它没有C++机制,,c++,coding-style,assert,C++,Coding Style,Assert,另一方面,C++定义了std::logic_error,这意味着在程序逻辑中出现错误的情况下抛出(因此得名)。抛出一个实例可能是比assert更完美、更像C++语言的选择 问题是assert和abort都会在不调用析构函数的情况下立即终止程序,因此跳过清理,而手动抛出异常会增加不必要的运行时成本。解决这个问题的一种方法是创建一个自己的断言宏SAFE\u ASSERT,它的工作原理与C对应的宏一样,但在失败时抛出一个异常 关于这个问题,我能想到三种观点: 坚持C的断言。由于程序会立即终止,因此是

另一方面,C++定义了
std::logic_error
,这意味着在程序逻辑中出现错误的情况下抛出(因此得名)。抛出一个实例可能是比
assert
更完美、更像C++语言的选择

问题是
assert
abort
都会在不调用析构函数的情况下立即终止程序,因此跳过清理,而手动抛出异常会增加不必要的运行时成本。解决这个问题的一种方法是创建一个自己的断言宏
SAFE\u ASSERT
,它的工作原理与C对应的宏一样,但在失败时抛出一个异常

关于这个问题,我能想到三种观点:

  • 坚持C的断言。由于程序会立即终止,因此是否正确展开更改并不重要。此外,在C++中使用<代码>定义< /代码> s也一样糟糕。
  • 抛出异常并在main()中捕获它。允许代码在程序的任何状态下跳过析构函数都是不好的做法,必须不惜一切代价避免,对terminate()的调用也是如此。如果抛出异常,则必须捕获它们
  • 抛出异常并让它终止程序。终止程序的异常是正常的,并且由于
    NDEBUG
    ,这在发布版本中永远不会发生。捕获是不必要的,它将内部代码的实现细节公开给
    main()
这个问题有明确的答案吗?有专业的参考资料吗


编辑:跳过析构函数当然不是未定义的行为 错误处理适用于可能恢复错误或向用户报告错误的情况。例如,如果试图读取输入文件时出现错误,您可能需要对此采取一些措施。错误可能是由错误引起的,但它们也可能是给定输入的适当输出

断言是用于检查API的需求是否得到满足,而API通常不会被检查,或者是用于检查开发人员认为他可以通过构造得到保证的东西。例如,如果一个算法需要排序的输入,您通常不会检查它,但您可能会有一个断言来检查它,以便调试构建标记这种错误。断言应始终指示操作不正确的程序


如果您正在编写一个程序,不干净的关机可能会导致问题,那么您可能希望避免断言。用C++语言严格定义的未定义行为在这里不符合此问题,因为击中断言可能是未定义行为的结果,或违反某些其他要求,这可能会阻止某些清理工作正常工作。 此外,如果您根据异常实现断言,那么它可能会被捕获并“处理”,即使这与断言的目的相矛盾。

  • 断言用于调试。您发布的代码的用户不应该看到它们。如果命中断言,则需要修复代码

该产品包含一个assert()或类似的语句,可以 由攻击者触发,导致应用程序退出或其他 比必要的更严重的行为

而断言有助于捕捉逻辑错误并减少错误 达到更严重的脆弱性条件的机会,它可以 仍然会导致拒绝服务

例如,如果服务器同时处理多个连接, 一个assert()发生在一个连接中,该连接导致所有其他连接 要删除的连接,这是一个可访问的断言,导致 拒绝服务

  • 例外情况适用于特殊情况。如果遇到这样的情况,用户将无法做她想做的事情,但可以在其他地方继续

  • 错误处理适用于正常程序流。例如,如果您提示用户输入一个数字并得到一些不可解析的结果,这是正常的,因为用户输入不在您的控制之下,您必须始终处理所有可能的情况。(例如,循环直到您有一个有效的输入,中间说“对不起,再试一次”。)


    • 由于alling abort()而不运行析构函数不是未定义的行为

      如果是,那么调用
      std::terminate()
      也将是未定义的行为,那么提供它有什么意义呢


      < > >代码>()/>代码>在C++中与C中一样有用。断言不是用于错误处理,而是用于立即中止程序。< /P> < P>断言可用于验证内部执行不变量,如执行某些方法之前或之后的内部状态,等等。如果断言失败,这实际上意味着程序的逻辑被破坏,您无法从中恢复。在这种情况下,您所能做的最好的事情就是尽快中断,而不将异常传递给用户。断言的真正好处(至少在Linux上)在于,核心转储是进程终止的结果,因此您可以轻松地研究堆栈跟踪和变量。这对于理解逻辑故障比异常消息要有用得多。

      IMHO,断言用于检查条件,如果违反了这些条件,则会使其他一切变得毫无意义。因此,你无法从中恢复,或者说,恢复是无关紧要的

      我将它们分为两类:

      • 开发人员sins(例如,概率函数