在C ++坏实践中使用assert()? [英] Is using assert() in C++ bad practice?

查看:135
本文介绍了在C ++坏实践中使用assert()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我倾向于添加大量的断言到我的C ++代码,使调试更容易,而不会影响发布版本的性能。现在, assert 是一个纯C的宏设计,没有C ++机制。

I tend to add lots of assertions to my C++ code to make debugging easier without affecting the performance of release builds. Now, assert is a pure C macro designed without C++ mechanisms in mind.

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

C++ on the other hand defines std::logic_error, which is meant to be thrown in cases where there is an error in the program's logic (hence the name). Throwing an instance might just be the perfect, more C++ish alternative to assert.

问题是, assert abort 都会立即终止程序而不调用析构函数,因此跳过清理,而抛出异常手动添加不必要的运行时成本。一个办法是创建一个自己的断言宏 SAFE_ASSERT ,它的工作原理就像C对应,但抛出一个失败的异常。

The problem is that assert and abort both terminate the program immediately without calling destructors, therefore skipping the cleanup, whereas throwing an exception manually adds unnecessary runtime costs. One way around this would creating an own assertion macro SAFE_ASSERT, which works just like the C counterpart, but throws an exception on failure.

我可以针对这个问题提出三点意见:


  • 坚持C的断言。由于程序会立即终止,因此更改是否正确展开无关紧要。此外,使用C ++中的 #define 也是同样糟糕。

  • 抛出异常并捕获它在main 。允许代码跳过程序的任何状态的析构函数是不好的做法,必须不惜一切代价,因此是对terminate()的调用。如果抛出异常,它们必须被捕获。

  • 抛出异常并终止程序。终止程序的异常可以, code> NDEBUG ,这在发行版中永远不会发生。捕获是不必要的,并且将内部代码的实现细节暴露给 main()

  • Stick to C's assert. Since the program is terminated immediately, it does not matter whether changes are correctly unrolled. Also, using #defines in C++ is just as bad.
  • Throw an exception and catch it in main(). Allowing code to skip destructors in any state of the program is bad practice and must be avoided at all costs, and so are calls to terminate(). If exceptions are thrown, they must be caught.
  • Throw an exception and let it terminate the program. An exception terminating a program is okay, and due to NDEBUG, this will never happen in a release build. Catching is unnecessary and exposes implementation details of internal code to main().

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

Is there a definitive answer to this problem? Any professional reference?

已编辑:跳过析构函数当然没有未定义的行为。

Edited: Skipping destructors is, of course, no undefined behaviour.

推荐答案

断言在C ++代码中是完全合适的。

Assertions are entirely appropriate in C++ code. Exceptions and other error handling mechanisms aren't really intended for the same thing as assertions.

错误处理是指当有可能恢复或报告错误的错误时,错误处理机制不是真正意图与断言相同的东西。用户。例如,如果尝试读取输入文件时出现错误,您可能需要执行一些操作。错误可能由错误引起,但它们也可以简单地是给定输入的适当输出。

Error handling is for when there's a potential for recovering or reporting an error nicely to the user. For example if there's an error trying to read an input file you may want to do something about that. Errors could result from bugs, but they could also simply be the appropriate output for a given input.

断言是为了检查API的要求是否满足API通常不会被检查,或者检查事情开发商认为他是由建设保证。例如,如果一个算法需要排序输入,你通常不会检查它,但你可能有一个断言来检查它,以便调试生成标志这种错误。

Assertions are for things like checking that an API's requirements are met when the API wouldn't normally be checked, or for checking things the developer believes he's guaranteed by construction. For example if an algorithm requires sorted input you wouldn't normally check that, but you might have an assertion to check it so that debug builds flag that kind of bug. An assertion should always indicate an incorrectly operating program.

如果你正在写一个程序,其中一个不正常的关闭可能会导致一个错误的操作程序。问题,那么你可能想要避免断言。在C ++语言中严格的未定义的行为在这里不适合作为这样的问题,因为击中一个断言可能已经是未定义的行为的结果,或者违反了一些可能阻止一些清理工作正常的其他要求。

If you're writing a program where an unclean shutdown could cause a problem then you may want to avoid assertions. Undefined behavior strictly in terms of the C++ language doesn't qualify as such a problem here, since hitting an assertion is probably already the result of undefined behavior, or the violation of some other requirement which could prevent some clean-up from working properly.

此外,如果你根据异常实现断言,那么它可能被捕获和处理,即使这违反了断言的目的。

Also if you implement assertions in terms of an exception then it could potentially be caught and 'handled' even though this contradicts the very purpose of the assertion.

这篇关于在C ++坏实践中使用assert()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆