[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: assert vs. abort
From: |
John Darrington |
Subject: |
Re: assert vs. abort |
Date: |
Sat, 1 Apr 2006 09:27:09 +0800 |
User-agent: |
Mutt/1.5.9i |
On Fri, Mar 31, 2006 at 10:27:01AM -0800, Ben Pfaff wrote:
> The notion (implied by the NDBUG mechanism) that assertions are
> something to be disabled in production code is a common one, but one
> that I think is misguided. I would only set NDEBUG in code where
> speed is absolutely critical, and pspp doesn't have that criteria.
This is a common argument and a very old one; C. A. R. Hoare said
something similar, although about array bounds checks, way back
in 1972, according to a citation by Knuth. I sympathize with the
sentiment. But I think it's flawed.
First: Some useful assertions are very expensive. Consider the
assertion at the end of binary_search() in array.c:
expensive_assert (find (array, count, size, value, compare, aux) ==
NULL);
This assertion is invoked when the binary search didn't find a
match. It linearly searches the array for a match. This
assertion can fail if the array was not actually sorted or if the
comparison function is wonky. That's something valuable to check
for, but it increases the cost of a failing binary search from
O(lg n) to O(n). That's normally acceptable for debugging, but
not good for real use.
Also: it's impossible to tell how much assertions actually cost
you unless you occasionally turn them off and run tests with and
without them. I've actually done this from time to time. It's
enlightening.
I didn't say that they should *never* be turned off. I said that
dogmatically turning them off for production code is not a good idea
(especially if all the quality assurance tests have been done with
them turned ON --- it's amazing how many sofware houses do this).
> Whilst were talking about these things, I'm not too happy with the
> current implementation of request_bug_report_and_abort(). One of the
> reasons it could get called is heap exhaustion. Any implementation of
> printf is free to use the heap, so we could end up with an infinite
> loop. I think the strings should be statically allocated on startup,
> and just shipped to stderr using fputs.
write(STDERR_FILENO, buf, buf_len) would be even more
conservative, because it wouldn't try to obtain the lock that
POSIX requires streams to have.
OK.
How about this:
ASSERT() -- for cheap, important checks
ASSERT1() -- for more expensive or less important checks
ASSERT2() -- for expensive checks
ASSERT_LEVEL -- if defined to a number, checks at the given
level or higher are disabled.
NOT_REACHED() -- as discussed
I'd be reasonably happy with that. presumably ASSERT{,1,2} simply
call ASSERT_LEVEL. And you might want to change 1 & 2 to symbols,
that way, we can insert a level between 1 and 2 at a later stage if we
find it becomes necessary.
The question remains then, what level of assertions should be enabled
when?
* I suppose for development all assertions are enabled?
* NOT_REACHED should *always* be enabled.
* Do we want to turn off some/all ASSERTs when doing make dist ? If
so, then we'd have to hack the automake rules, to set the relevant
assertion level and do a clean rebuild.
* Some systems I've seen have allow the assert/debug/log level to be
set at runtime (through a config file). Further, some allow a
"domain" flag in addition to the level (eg {PARSER,OUTPUT,DATA
etc}). Although the complexity of such systems usually means
that most developers don't understand how to use them, so they
either avoid using it, or else they misuse it and thus render it
useless for the few people who actually do know how to use it
properly.
J'
--
PGP Public key ID: 1024D/2DE827B3
fingerprint = 8797 A26D 0854 2EAB 0285 A290 8A67 719C 2DE8 27B3
See http://pgp.mit.edu or any PGP keyserver for public key.
signature.asc
Description: Digital signature