setjmp return value as the right-hand side of a assignmentexpression?

Discussion in 'C Programming' started by essai, Jul 27, 2009.

  1. essai

    essai Guest

    Hi all,
    In the book "C A reference manual" (Samuel P. Harbison III & Guy L.
    Steele Jr) p.455, it is said:
    "Standard C requires that the call to setjmp either be ..., the right-
    hand side of a simple assignment expression, or ..."

    I looked at the standard and found:

    "Environmental limits
    4 An invocation of the setjmp macro shall appear only in one of the
    following contexts:
    — the entire controlling expression of a selection or iteration
    — one operand of a relational or equality operator with the other
    operand an integer
    constant expression, with the resulting expression being the entire
    expression of a selection or iteration statement;
    — the operand of a unary ! operator with the resulting expression
    being the entire
    controlling expression of a selection or iteration statement; or
    — the entire expression of an expression statement (possibly cast to
    5 If the invocation appears in anyother context, the behavior is

    So, according to the Standard C, a statement like this:

    jmp_buf env;
    int status = setjmp(env);

    leads to undefined behaviour, but according to Harbison and Steele, is
    perfectly defined.
    Who's right? who's wrong?
    Thanks by advance, all.
    essai, Jul 27, 2009
    1. Advertisements

  2. essai

    Eric Sosman Guest

    The International Standard that defines the C programming
    language is wrong, *obviously*. How could it be otherwise?

    H&S is not the worst existing book on C, but it is the
    worst that I happen to possess. (An earlier edition than yours,
    apparently, as mine has only 392 pages including the index.)
    The first code example in my copy, the very first example that
    introduces a brand-new reader to C for the very first time, is
    a four-line source file defining one function:

    void hello()
    printf ("Hello!\n");

    No, the "Reference Manual" does not even mention that this
    function would produce undefined behavior if ever called ...
    (A C99 compiler would issue a diagnostic, but my H&S dates
    from 1991 and can be forgiven for overlooking developments
    that were still eight years in the future. But the function
    produces undefined behavior even under the C90 rules that
    prevailed when it was written -- So what is one to think of
    the level of expertise and/or attention to detail exhibited
    by Messrs. H and S? One hopes they've improved matters in
    more recent editions, but I'm not highly motivated to spend
    money to find out -- and your report of their description of
    setjmp() suggests that my parsimony has not disadvantaged me.)
    Eric Sosman, Jul 27, 2009
    1. Advertisements

  3. essai

    essai Guest

    I have the fifth version (2002) of "C A reference manual" and use
    n1256 (C99 TC3 september 2008) as Standard C.
    essai, Jul 27, 2009
  4. essai

    Eric Sosman Guest

    Okay: In case I wasn't clear earlier (tone of voice doesn't
    always survive transcription into plain text, so sarcasm and
    irony are sometimes lost):

    - The Standard is right (by definition)
    - H&S are wrong (they contradict the Standard)

    End of story.
    Eric Sosman, Jul 27, 2009
  5. essai

    Mark Bluemel Guest

    H & S could be correct about what happens in practice with such real-
    world implementations as they have encountered. Their contradiction of
    the Standard cannot be taken as generally applicable - the Standard is
    the standard, the last word, the ex-cathedra statement...
    Mark Bluemel, Jul 27, 2009
  6. in many projects, one may often have to step "around" the standards...

    granted, it is also good to follow the standards, when applicable.

    in general, this leads to an odd pattern:
    a good portion of a codebase is relatively portable.

    other parts, may be almost completely non-portable.

    if done well, the non-portable parts can be rewritten/replaced with
    relatively little effort, and would serve mostly to provide capabilities
    "not otherwise possible" (and, as a cost, dig fairly deeply into the
    underlying implementation...).

    typically, these distinctions are made either by partitioning the code into
    specific source files (non-portable code being designated as such), or
    through the use of '#ifdef' and friends...

    even then, one has to be careful that their #ifdef's are also portable
    (different compilers may indicate the CPU arch, OS, ... in rather different

    or such...
    BGB / cr88192, Jul 27, 2009
  7. essai

    jameskuyper Guest

    I thought it would be a good idea to emphasize that the attitude being
    expressed by Eric is not, as some have suggested, a cult-like
    blindness to the possibility of defects in the standard. The
    standard's description of the C language and the C library could be
    incorrectly worded, internally inconsistent, or out of sync with real
    world C compilers. The language or the library that the standard
    describes might be poorly designed, or even impossible to implement.
    The actual standard contains examples of a few of these defects.
    However, the one thing the Standard cannot be is incorrect; that's
    simply because the standard defines what "correct" means in the
    context of C.
    jameskuyper, Jul 27, 2009
  8. In the 5th edition, that example is:

    #include <stdio.h> /* defines printf */
    void hello(void)

    The comment should say "declares" rather than "defines", but the code
    is solid.
    I think the 5th edition's description of setjmp now also agrees with
    the standard.
    Keith Thompson, Jul 27, 2009
  9. You're right, H&S5 gets this wrong. (essai didn't actually say
    the quotation is from the 5th edition, but it is; the page numbers
    match.) And that error doesn't appear in the errata either; see
    Keith Thompson, Jul 27, 2009
  10. Whoops, essai did mention the 5th edition in a followup.

    I've e-mailed a correction to the authors, cc'ed to essai.
    Keith Thompson, Jul 27, 2009
  11. which would be wrong
    but not in the case of setjmp()! As others have pointed out there
    are good reasons for the apparently arbitary restrictions on setjmp()
    calls. The whole setjmp/logjmp system is fragile and shouldn't
    be stresssed in any way. See Plauger "The Standard C Library" for
    discussion (coincidently I was just re-reading it and I've just
    read the setjmp/longjmp bit. Scarey).

    doesn't seem at all odd to me! How else would you write code! :)
    Seriously, this is what your code *should* look like.

    avoid the ifdef way if you possibly can. It leads to messy and obscure
    code. Far better is to use architecture specific files.
    Nick Keighley, Jul 28, 2009
  12. It depends on how different the target systems are; if I were writing a
    thread API wrapper, for example, I'd probably put Windows and POSIX in
    separate implementation files -- but if Linux, Solaris, and OSX each
    required a few lines of tweaks to the POSIX wrapper, the mental cost of
    the #ifdefs is lower than the mental cost of maintaining three different
    wrappers that were virtually identical.

    Stephen Sprunk, Jul 28, 2009
  13. essai

    jqbalter Guest

    Is this a joke? How could the Standard for what is and is not defined behavior be wrong? That's not coherent.
    jqbalter, Apr 7, 2014
  14. essai

    Ian Collins Guest

    Replying to a post from 2009 certainly is!
    Ian Collins, Apr 7, 2014
  15. essai

    jqbalter Guest

    Less so that your substance-free comment.
    jqbalter, Apr 7, 2014
  16. This was discussed here at some length when essai's article was
    posted 5 years ago. If you were able to find that old post, you
    should be able to find the rest of the discussion. Conclusion:
    This is an error in Harbison & Steele; I e-mailed a correction to
    the authors at the time.

    Incidentally, that error still doesn't appear in the errata at
    Keith Thompson, Apr 7, 2014
  17. essai

    jqbalter Guest

    I'm not unaware of any of that but it has no bearing on my comment, which will still be valid when the discussion is a billion years old. The fact is that this thread is still being *referenced*, which is how I ended up here.
    jqbalter, Apr 7, 2014
  18. essai

    jqbalter Guest

    BTW, the problem that I addressed in Essai's comment is that Essai, among many other people, don't understand what "undefined behavior" is. Essai's question was whether the given code "leads to undefined behaviour", as if "undefined behavior" were some *concrete* behavior displayed by various implementations, rather than a characterization of such code by the defining document of not having defined behavior. Every implementation in the universe could do exactly what we would like it to do and it would still be undefinedbehavior. (And yes, I know that language lawyers such as Keith Thompson already know this.)
    jqbalter, Apr 7, 2014
  19. essai

    James Kuyper Guest

    Where was it referenced? It might be more appropriate to comment on the
    reference, in the same context as the one where the reference occurred.

    If the entire thread was referenced, what goal are you trying to achieve
    by commenting on it now? Anybody who looks at the entire thread will see
    that the point you're making was already made by other people, long
    before you made it.
    James Kuyper, Apr 7, 2014
  20. essai

    Kaz Kylheku Guest

    There are two problems with

    x = setjmp(...);

    One is surmountable; the other isn't.

    The first problem is that if x is a variable with automatic storage which is
    not volatile-qualified, then the above constitutes an instance of modifying a
    non-volatile auto variable after doing a setjmp, before the longjmp takes
    place. The value of such a variable is indeterminate. (See paragraph in
    description of longjmp.)

    The second problem is that when control returns into the setjmp() expression
    for a second time via the longjmp invocation, the setjmp-time environment
    (all accessible objects) is being restored.

    So, imagine that setjmp is being re-activated by a longjmp and is restoring the
    value of x:

    x = setjmp(...);

    But remember that setjmp is not a function, but a macro. It doesn't have a
    sequence point between its restoring actions, and the action of returning a
    value. So the above constitutes two modifications of object x without an
    intervening sequence point.
    Kaz Kylheku, Apr 7, 2014
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.