Path: utzoo!attcan!uunet!lll-winken!sun-barr!cs.utexas.edu!chinacat!sequoia!rpp386!jfh From: jfh@rpp386.cactus.org (John F. Haugh II) Newsgroups: comp.unix.internals Subject: asserts and unexpected returns (was: Re: Assert) Summary: still no clue. Message-ID: <18662@rpp386.cactus.org> Date: 31 Oct 90 14:19:41 GMT References: <18647@rpp386.cactus.org> <4057@awdprime.UUCP> <18658@rpp386.cactus.org> <4093@awdprime.UUCP> Reply-To: jfh@rpp386.cactus.org (John F. Haugh II) Followup-To: alt.flame Organization: HASA, "S" Division Lines: 153 X-Clever-Slogan: Recycle or Die. In article <4093@awdprime.UUCP> daveb@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 . % grep -y ASSERT /usr/include/sys/debug.h % hmmm. no ASSERT (or assert) in my . 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 #include #include 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@rpp386.cactus.org "SCCS, the source motel! Programs check in and never check out!" -- Ken Thompson