[comp.unix.programmer] asserts

daveb@nostromo.austin.ibm.com (Dave Burton) (10/31/90)

[ follow-ups redirected to comp.unix.programmer ]

In article <18658@rpp386.cactus.org> jfh@rpp386.cactus.org (John F. Haugh II) writes:
|so, you will always assume that failing asserts never return?  this
|means that your portable programs aren't.

The only way for a SVR2,3 assert() to return is _if_ SIGIOT is not
SIG_DFL.  Most programs do not blithely SIG_IGN all signals.  Further,
BSD/AIX/other asserts can _never_ return.  So, yes, I always% assume
failing asserts() never return - that is their design.  As for portability,
see below.

% given the caveat of SIGIOT peculiarities on SVR2,3 systems

|you could splatter your code with feature test macros for each
|and every one of those versions you listed, with special behavior
|to be followed.  or you could take the easy way out, listen to
|your uncle fred, and just put an exit after failing assert()
|calls.  this is easy, portable, and foolproof.  it has the novel
|property that it always works.

It is obvious that you did not read what I wrote.
Repeat after me: "assert() is a macro, not a function."
If I put an exit() after an assert() call, it looks like:

	#include <assert.h>
	#include <signal.h>
	main(argc) {
		signal(SIGIOT, SIG_IGN);
		assert(argc==2);
		exit(1);
		printf("argc is equal to 2\n");
	}

Well, clearly this won't work.  How about:

		if (assert(argc==2) == -1)
			exit(1);

Oh.  Syntax error.  Looking at assert.h reveals the definition:

	#define assert(EX) if (EX) ; else _assert("EX", __FILE__, __LINE__)

Gee, "Uncle Fred", how do you put a conditional exit() in your code?
Surely you wouldn't do:

		assert(argc==2),exit(1);

would you?  What happens when NDEBUG is #define'd?  Syntax error.
The only way to put an exit() after a failing assert() is to
rework the macro, which is not portable.

|but the kernel assert() function is not defined
|in the System V Programmer's Reference Manual sitting next to me.
|i checked the namelist on the kernel running here.

This could be my fault for not accurately describing the kernel assert
mechanism for you.  The _macro_ name (it _won't_ appear in any namelist,
just like user asserts) is ASSERT().  It invokes assfail() the same way
user assert() invokes _assert().  And assfail() will _not_ return.
Refer to <sys/debug.h>.

|no assert.  hmmm.
|perhaps this is another IBMism?  always assume the worst; never
|count on undocumented behavior or nonstandard features.

Perhaps you should do a little more research before sermonizing?

|the point of this article was to illustrate that ignoring unexpected
|returns can lead to unexpected results, not to serve as an
|oppurtunity for someone to research every version of assert().

I admit, I did look at the sources to verify my understanding
before posting to the net.  That's generally considered wise.
Perhaps you would fare better if you did the same.
--
Dave Burton
inet: daveb@bach.austin.ibm.com
uucp: cs.utexas.edu!ibmchs!auschs!nostromo!daveb