asserts and unexpected returns (was: Re: Assert)

John F. Haugh II jfh at rpp386.cactus.org
Thu Nov 1 01:19:41 AEST 1990


In article <4093 at awdprime.UUCP> daveb at bach.austin.ibm.com (Dave Burton) writes:
>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

yes, quite a few of my programs do run off on a tear and blithely
ignore all of their signals.

one thing you are ignoring is how many systems have the behavior
which i describe.  it is not just limited to SVR2 and SVR3, it
includes every AT&T release prior to SVR2, such as 3.0, 4.0, 7th
Edition, etc, and non-AT&T versions of UNIX-like operating systems
as well.  it is reasonable to expect abort() to return if SIGIOT
is ignored.  it doesn't matter what you think assert() is designed
to do, there is so much prior art which contradicts your expectation.
unfortunately there is also some prior art which agrees with what
you are saying, and that is why i say to expect the worst - you
lose nothing if you do, but if you don't you may have expected
return conditions you aren't prepared to handle.

i checked the old X3J11 draft i have - it was silent on the
issue.  now, i don't know if ANSI C requires abort() to exit,
but if it doesn't, we still have this problem in ANSI C.  using
unspecified or undefined behavior is the very definition of
non-portable.  even if ANSI C, X/OPEN and half a dozen other
standards all agree with you, there is simply too much prior
experience with other behavior.

>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:

then don't do it that way.

>		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.

this is too easy.

you put a conditional.  then you put an exit.  this gives you
a conditional exit statement.  most programmers don't have
trouble with this.  many of them even write code like

	if (! (chunk = malloc (sizeof *chunk))) {
		perror ("oops");
		exit (1);
	}

how about (gee, just a suggestion, i normally charge for my
programming lessons, so this isn't a programming lesson)

	if (! (chunk = malloc (sizeof *chunk))) {
		perror ("oops");
		assert (chunk != 0);
		exit (1);
	}

now, i'd never actually do this, so don't think i am advocating
this exact code fragment.  but gee, dave, it isn't that hard.

>|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>.

% grep -y ASSERT /usr/include/sys/debug.h
%

hmmm.  no ASSERT (or assert) in my <sys/debug.h>.  perhaps this really
is just another IBMism.  perhaps this is implementation specific
details which have no bearing in a discussion of portable programming
practices?

furthermore, i don't recall any requirement in any of the documentation
i've read requiring assert() invoke _assert() or assfail() or any of
the stuff you keep talking about.  please, try to limit this discussion
to documented features.  let's start with this documented feature -

	"assert(S)

	 if expression is false (zero), it displays ... on the
	 standard error file and aborts."

and then this documented feature -

	"abort(S)

	 abort can return control if the calling process is set
	 to catch or ignore SIGIOT ..."

5.0 documentation is even more explicit.

>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.

are you in the habit of violating your non-disclosure agreements
with IBM and AT&T just so you can make your postings?  many of the
people in this group have access to source code as well, but most
of us don't run off and read it then report what we find to the
net.

just so you get to see how this =really= works in the =real=
world, try this -

Script is typescript, started Wed Oct 31 08:09:42 1990
rpp386-> cat abort.c
#include <signal.h>
#include <assert.h>
#include <stdio.h>

main (argc, argv)
int	argc;
char	**argv;
{
	signal (SIGIOT, SIG_IGN);
	assert (argc == 2);
	printf ("hi dave!\n");
}
rpp386-> cc -o abort abort.c
abort.c
rpp386-> ./abort
Assertion failed: expr, file abort.c, line 10
hi dave!
rpp386-> exit
Script done Wed Oct 31 08:10:00 1990
-- 
John F. Haugh II                             UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 832-8832                           Domain: jfh at rpp386.cactus.org
"SCCS, the source motel!  Programs check in and never check out!"
		-- Ken Thompson



More information about the Comp.unix.internals mailing list