I am finding that using assert(...)
makes my code shorter and easier to read, as opposed to lengthy if..else..
blocks. However, are there good technical reasons not to use assert(...)
in shipping code, when it does the same thing as testing a return
value while using less code?
相关问题
- Multiple sockets for clients to connect to
- What is the best way to do a search in a large fil
- glDrawElements only draws half a quad
- Index of single bit in long integer (in C) [duplic
- Equivalent of std::pair in C
Asserts are good. Compile-time asserts are even better. Note:
BOOST_STATIC_ASSERT()
.static_assert()
.static_assert()
: Does GCC have a built-in compile time assert?static_assert()
(<assert.h>
).If your environment doesn't already have a static assert, here is a suggestion.
The
ASSERT()
macro given below can be placed anywhere in the code, except:#ifndef...#endif
wrapper.If you want stick something in the middle of a structure definition you'll need to use the lengthy, ugly, three-line construct
#if...#error...#endif
. And if you do do this, the pre-processor has a much more limited idea of what a "constant expression" is.This is a refinement of ideas from the web, primarily from http://www.pixelbeat.org/programming/gcc/static_assert.html. This definition is shorter than
BOOST_STATIC_ASSERT()
. And, I believe, is better than Linus's suggestion for an improvedBUILD_BUG_ON()
. And thedo{...}while(0)
wrapper you commonly see is totally inapplicable here, as it limits permissible locations.This is also simpler than Google's COMPILE_ASSERT/CompileAssert. The 'sizeof bitfield' trick also seems good, from Linux's
BUILD_BUG_ON_ZERO()
, but not its useless siblingBUILD_BUG_ON()
.There are many suggestions for using arrays with a negative index. But with GCC, most of these do not detect a non-constant arg (which is easy enough to do in error), except for the 'extern int foo[expression]', which also gives an 'unused variable' warning. But
typedef int array[expression]
seems also to be good: see below.The definition:
Equally good, I believe, is the following variant, but it is longer by five characters:
There is also the
do{switch(0){case 0:case(e):;}}while(0)
construct, which I haven't investigated.Sometimes one needs a variant to handle the case where two different header files happen by chance to have two ASSERT()'s on the same line, or likewise for a source file and a header file. You could handle this via
__COUNTER__
, but this isn't supported by some compilers (and is uglier). And we can't use__FILE__
, because it doesn't usually expand to a valid C token (e.g. it has a dot c or dot h). The Mozilla version http://mxr.mozilla.org/mozilla-central/source/mfbt/Assertions.h states that such conflicts "should be rare", but they'll greatly annoy your teammates when it happens. This can also be used to handle severalASSERTS
in a multi-line macro, where__LINE__
doesn't change.The next variant,
ASSERT_zero(),
is similar toBUILD_BUG_ON_ZERO(),
using the 'sizeof bitfield' trick. This yields either:e
is false, orSo it can be used in places where a statement cannot, such as in the middle of an expression.
While the other answers have some good information, none seems (to me) to have directly addressed the question you asked.
IMO, yes, there's a fairly significant shortcoming to leaving
assert
s in (most) production code: you get no control over the error message it displays, which is often rather scary looking.Instead of something like:
I'd rather give the customer something like:
Like java Exceptions
assert
gives a fail-fast. That is a very good practice saving much development time and effort. But the shipping code should have fast releases as a web application, and not something like a CD distro. Furthermore in java exceptions may be intercepted, logged and nicely presented.