C++ 断言是邪恶的吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1854302/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is assert evil?
提问by Frank
The Go
language creators write:
该Go
语言的创造者写的:
Go doesn't provide assertions.They are undeniably convenient, but our experience has been that programmers use them as a crutch to avoid thinking about proper error handling and reporting. Proper error handling means that servers continue operation after non-fatal errors instead of crashing. Proper error reporting means that errors are direct and to the point, saving the programmer from interpreting a large crash trace. Precise errors are particularly important when the programmer seeing the errors is not familiar with the code.
Go 不提供断言。不可否认,它们很方便,但我们的经验是程序员将它们用作拐杖,以避免考虑正确的错误处理和报告。正确的错误处理意味着服务器在非致命错误后继续运行而不是崩溃。正确的错误报告意味着错误是直接的、切中要害的,使程序员免于解释大的崩溃跟踪。当看到错误的程序员不熟悉代码时,精确的错误尤其重要。
What is your opinion about this?
您对此有何看法?
回答by caf
No, there's nothing wrong with assert
as long as you use it as intended.
不,assert
只要您按预期使用它就没有问题。
That is, it's supposed to be for catching cases that "can't happen", during debugging, as opposed to normal error handling.
也就是说,它应该用于在调试期间捕获“不可能发生”的情况,而不是正常的错误处理。
- Assert: A failure in the program's logic itself.
- Error Handling: An erroneous input or system state not due to a bug in the program.
- 断言:程序逻辑本身的故障。
- 错误处理:错误的输入或系统状态不是由于程序中的错误引起的。
回答by gahooa
No, neither goto
nor assert
are evil. But both can be misused.
不,既不邪恶goto
也不assert
邪恶。但两者都可能被滥用。
Assert is for sanity checks. Things that should kill the program if they are not correct. Not for validation or as a replacement for error handling.
断言用于健全性检查。如果不正确,应该杀死程序的事情。不用于验证或作为错误处理的替代品。
回答by jalf
By that logic, breakpoints are evil too.
按照这个逻辑,断点也是邪恶的。
Asserts should be used as a debugging aid, and nothing else. "Evil" is when you try using them insteadof error handling.
断言应该用作调试辅助工具,仅此而已。“邪恶”是当您尝试使用它们而不是错误处理时。
Asserts are there to help you, the programmer, detect and fix problems that must not exist and verify that your assumptions stay true.
断言可以帮助您,程序员,检测和修复不应该存在的问题,并验证您的假设是否成立。
They have nothing to do with error handling, but unfortunately, some programmers abuse them as such, and then declare them "evil".
它们与错误处理无关,但不幸的是,一些程序员滥用它们,然后宣称它们是“邪恶的”。
回答by arhuaco
I like to use assert a lot. I find it very useful when I am building applications for the first time (perhaps for a new domain). Instead of doing very fancy error checking (that I would consider premature optimization) I code fast and I add a lot of asserts. After I know more about how things work I do a rewrite and remove some of the asserts and change them for better error handling.
我很喜欢使用断言。当我第一次构建应用程序时(也许是一个新域),我发现它非常有用。我没有进行非常花哨的错误检查(我会考虑过早优化),而是快速编码并添加了很多断言。在我更多地了解事情的工作原理后,我进行了重写并删除了一些断言并更改它们以更好地处理错误。
Because of asserts I spend a lot of less time coding/debugging programs.
由于断言,我花在编码/调试程序上的时间少了很多。
I've also noticed that the asserts help me think of many things that could break my programs.
我还注意到断言帮助我想到了许多可能会破坏我的程序的事情。
回答by Randy Sugianto 'Yuku'
As an additional information, go provides a built-in function panic
. This can be used in place of assert
. E.g.
作为附加信息,go 提供了一个内置函数panic
。这可以用来代替assert
. 例如
if x < 0 {
panic("x is less than 0");
}
panic
will print the stack trace, so in some way it has the purpose of assert
.
panic
将打印堆栈跟踪,因此在某种程度上它具有assert
.
回答by Alex Budovski
They should be used for detecting bugs in the program. Not bad user input.
它们应该用于检测程序中的错误。不错的用户输入。
If used correctly, they are notevil.
如果使用得当,它们不是邪恶的。
回答by jtolle
This comes up a lot, and I think one problem that makes defenses of assertions confusing is that they are often based on argument checking. So consider this different example of when you might use an assertion:
这种情况经常出现,我认为使断言辩护令人困惑的一个问题是它们通常基于参数检查。因此,请考虑何时可以使用断言的不同示例:
build-sorted-list-from-user-input(input)
throw-exception-if-bad-input(input)
...
//build list using algorithm that you expect to give a sorted list
...
assert(is-sorted(list))
end
You use an exception for the input because you expect you'll get bad input sometimes. You assert that the list is sorted to help you find a bug in your algorithm, which by definition you don't expect. The assertion is in the debug build only, so even though the check is expensive, you don't mind doing it on every single invocation of the routine.
您对输入使用异常是因为您希望有时会得到错误的输入。您断言该列表已排序以帮助您找到算法中的错误,根据定义,这是您不期望的。断言仅在调试版本中,因此即使检查很昂贵,您也不介意在每次调用例程时都这样做。
You still have to unit-test your production code, but that's a different, and complementary, way of making sure your code is correct. Unit tests make sure your routine lives up to its interface, while assertions are a finer-grained way to make sure your implementation is doing exactly what you expect it to.
您仍然需要对您的生产代码进行单元测试,但这是确保您的代码正确的一种不同且互补的方式。单元测试确保您的例程符合其接口,而断言是一种更细粒度的方法,可确保您的实现完全按照您的期望执行。
回答by figurassa
Assertions are not evil but they can be easily misused. I do agree with the statement that "assertions are often used as a crutch to avoid thinking about proper error handling and reporting". I have seen this quite often.
断言并不邪恶,但它们很容易被滥用。我确实同意“断言经常被用作避免考虑正确的错误处理和报告的拐杖”的说法。我经常看到这种情况。
Personally, I do like to use assertions because they document assumptions that I might have made whilst writing my code. If these assumptions are broken while maintaining the code, the problem can be detected during test. However, I do make the point of stripping out every assert from my code when doing a production build (i.e., using #ifdefs). By stripping out the assertions in the production build, I eliminate the risk of anyone misusing them as a crutch.
就我个人而言,我确实喜欢使用断言,因为它们记录了我在编写代码时可能做出的假设。如果在维护代码时破坏了这些假设,则可以在测试期间检测到问题。但是,在进行生产构建(即,使用#ifdefs)时,我确实会从我的代码中删除每个断言。通过去除生产构建中的断言,我消除了任何人将它们误用为拐杖的风险。
There is also another problem with assertions. Assertions are only checked at run-time. But it is often the case that the check you would like to perform could have been performed at compile-time. It is preferable to detect an issue at compile time. For C++ programmers, boost provides BOOST_STATIC_ASSERT which allows you to do this. For C programmers, this article ( link text) describes a technique that can be used to perform assertions at compile time.
断言还有另一个问题。断言只在运行时检查。但通常情况下,您想要执行的检查可能已在编译时执行。最好在编译时检测问题。对于 C++ 程序员,boost 提供 BOOST_STATIC_ASSERT 允许您执行此操作。对于 C 程序员,本文(链接文本)描述了一种可用于在编译时执行断言的技术。
In summary, the rule of thumb I follow is: Do not use assertions in a production build and, if possible, only use assertions for things that cannot be verified at compile-time (i.e., must be checked at run-time).
总之,我遵循的经验法则是:不要在生产构建中使用断言,如果可能,只对无法在编译时验证的事情使用断言(即,必须在运行时检查)。
回答by Newtopian
I dislike asserts intensely. I would not go as far as saying they are evil though.
我非常不喜欢断言。我不会说他们是邪恶的。
Basically an assert will do the same thing as an unchecked exception would, the only exception is that the assert (normally) should not be kept for the final product.
基本上,断言将与未检查的异常做同样的事情,唯一的例外是断言(通常)不应该为最终产品保留。
If you build a safety net for yourself while debugging and building the system why would you deny this safety net for your customer, or your support help desk, or anyone that will get to use the software that you are currently building. Use exceptions exclusively for both asserts and exceptional situations. By creating an appropriate exception hierarchy you will be able to discern very quickly one from the other. Except this time the assert remains in place and can provide valuable information in case of failure that would otherwise be lost.
如果您在调试和构建系统时为自己构建了一个安全网,为什么要拒绝为您的客户、您的支持服务台或任何将使用您当前构建的软件的人提供这个安全网。将异常专门用于断言和异常情况。通过创建适当的异常层次结构,您将能够非常快速地区分一个和另一个。除了这一次,断言仍然存在,并且可以在失败的情况下提供有价值的信息,否则会丢失。
So I fully understand the creators of Go by removing asserts altogether and forcing programmers to use exceptions to handle the situation. There is a simple explanation for this, exception are just a better mechanism for the job why stick with the archaic asserts?
所以我完全理解 Go 的创造者,完全删除断言并强迫程序员使用异常来处理这种情况。对此有一个简单的解释,例外只是一种更好的工作机制,为什么要坚持古老的断言?
回答by Pavel Radzivilovsky
I prefer avoiding code that does different things in debug and release.
我更喜欢避免在调试和发布中做不同事情的代码。
Breaking in the debugger on a condition and having all file/line info is useful though, also the exact expression and the exact value.
在条件下中断调试器并拥有所有文件/行信息很有用,还有确切的表达式和确切的值。
Having an assert that would "evaluate the condition only in debug" may be a performance optimization, and as such, useful only in 0.0001% of programs - where people know what they are doing. In all other cases this is harmful, as the expression may actually change program's state:
拥有“仅在调试中评估条件”的断言可能是一种性能优化,因此,仅在 0.0001% 的程序中有用 - 人们知道他们在做什么。在所有其他情况下,这是有害的,因为表达式实际上可能会改变程序的状态:
assert(2 == ShroedingersCat.GetNumEars());
would make the program do different things in debug and release.
assert(2 == ShroedingersCat.GetNumEars());
会使程序在调试和发布时做不同的事情。
We have developed a set of assert macros which would throw an exception, and do it in both debug and release version. For instance, THROW_UNLESS_EQ(a, 20);
would throw an exception with what() message having both file, line and the actual valuesof a, and so on. Only a macro would have the power for this. The debugger may be configured to break at 'throw' of the specific exception type.
我们开发了一组断言宏,它们会抛出异常,并在调试和发布版本中执行。例如,THROW_UNLESS_EQ(a, 20);
会抛出一个包含文件、行和 a 的实际值的what() 消息的异常,等等。只有宏才有能力做到这一点。调试器可以配置为在特定异常类型的“抛出”处中断。