在C ++不好的做法中使用assert()?

我倾向于为我的C ++代码添加大量断言,以便在不影响发布版本性能的情况下进行debugging。 现在, assert是一个纯粹的Cmacros,没有考虑C ++机制。

另一方面,C ++定义了std::logic_error ,它是在程序逻辑(因此名称)出现错误的情况下抛出的。 抛出一个实例可能只是完美的,更多的C ++ ish替代assert

问题是, assertabort都立即终止程序而不调用析构函数,因此跳过清理,而手动抛出exception增加了不必要的运行成本。 解决这个问题的一个办法是创build一个自己的断言macrosSAFE_ASSERT ,它的作用就像C对应的一样,但是在失败的时候抛出一个exception。

我可以想到关于这个问题的三点意见:

  • 坚持C的断言。 由于程序立即终止,修改是否正确展开并不重要。 另外,在C ++中使用#define也是一样糟糕。
  • 抛出一个exception,并在main()中捕获它 。 允许代码在程序的任何状态下跳过析构函数都是不好的做法,必须不惜一切代价来避免,所以调用terminate()。 如果抛出exception,则必须被捕获。
  • 抛出一个exception,让它终止程序。 终止程序的exception是可以的,并且由于NDEBUG ,这在发布版本中不会发生。 捕捉是不必要的,并将内部代码的实现细节公开给main()

这个问题有一个明确的答案吗? 任何专业的参考?

编辑:跳过析构函数当然是没有不确定的行为。

断言在C ++代码中是完全合适的。 exception和其他error handling机制并不是与断言相同的东西。

error handling适用于有可能恢复或向用户报告错误的情况。 例如,如果尝试读取input文件时出现错误,则可能需要对此进行操作。 错误可能是由错误引起的,但也可能是给定input的合适输出。

断言是指在检查API时,检查是否符合API的要求,或者检查开发人员相信他是否通过构build保证的事情。 例如,如果一个algorithm需要sorting的input,你通常不会检查,但你可能有一个断言来检查它,以便debugging构build标志这种错误。 断言应该总是指示一个不正确的操作程序。


如果你正在编写一个不清洁的关机会导致问题的程序,那么你可能要避免断言。 未定义的行为严格地用C ++语言来说,在这里没有资格成为这样一个问题,因为触发一个断言可能已经是未定义行为的结果,或者违反了可能阻止某些清理工作正常工作的其他一些要求。

同样,如果你用exception来实现断言,那么它可能会被抓住和“处理”,即使这与断言的目的相矛盾。

  • 断言是为了debugging 。 您提供的代码的用户不应该看到它们。 如果一个断言被击中,你的代码需要被修复。

  • 例外情况是特殊情况 。 如果遇到了,用户将无法做到自己想做的事情,但可能可以在其他地方恢复。

  • error handling是针对正常的程序stream程的。 例如,如果您提示用户input一个数字并得到一些不可分的东西,这是正常的 ,因为用户input不在您的控制之下,您必须始终处理所有可能的情况。 (例如循环,直到你有一个有效的input,并在中间说“对不起,再试一次”)。

断言可以用来validation内部实现的不variables,比如执行一些方法之前或之后的内部状态,等等。如果断言失败了,这实际上意味着程序的逻辑被破坏,你不能从中恢复。 在这种情况下,你所能做的最好的事情就是尽可能快地中断,而不会传递给用户。 断言(至less在Linux上)真正好的是核心转储是由于进程终止而产生的,因此你可以很容易地调查堆栈跟踪和variables。 理解逻辑故障比exception消息更有用。

由于allorting()不会运行析构函数,所以不是未定义的行为!

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

assert()在C ++中与C中一样有用。断言不是用于error handling,而是用于立即中止程序。

恕我直言,断言是检查条件,如果违反,使所有其他的废话。 因此,你不能从中恢复,或者说,恢复是无关紧要的。

我将他们分为两类:

  • 开发者罪(例如返回负值的概率函数):

float probability(){return -1.0; }

断言(概率()> 0.0)

  • 机器坏了(例如运行你的程序的机器是非常错误的):

int x = 1;

assert(x> 0);

这些都是微不足道的例子,但离现实还不太远。 例如,考虑使用向量返回负指数的朴素algorithm。 或者定制硬件中的embedded式程序。 或者是因为狗屎发生

如果有这样的开发错误,你不应该有任何恢复或error handling机制实施的信心。 这同样适用于硬件错误。