exit, atexit and scope

Discussion in 'C Programming' started by Laurent Deniau, Nov 15, 2007.

  1. I would like to know if the use of the pointer ref in the function
    cleanup() below is valid or if something in the norm prevents this
    kind of cross-reference during exit(). I haven't seen anything in the
    norm against this, I mean an as-if rule saying "atexit registered
    functions are executed as-if they were called from main", making val
    out of scope at this point.

    a+, ld.

    #include <stdio.h>
    #include <stdlib.h>

    int *ref;

    void cleanup(void) {
    if (ref) fprintf(stderr, "val = %d\n", *ref);
    }

    void test(void) {
    int val = 12;
    ref = &val;
    exit(EXIT_FAILURE);
    }

    int main(void) {
    atexit(cleanup);
    test();
    return 0;
    }
    Laurent Deniau, Nov 15, 2007
    #1
    1. Advertising

  2. Laurent Deniau <> writes:

    > I would like to know if the use of the pointer ref in the function
    > cleanup() below is valid or if something in the norm prevents this
    > kind of cross-reference during exit(). I haven't seen anything in the
    > norm against this, I mean an as-if rule saying "atexit registered
    > functions are executed as-if they were called from main", making val
    > out of scope at this point.


    You don't mean scope. You are talking about the lifetime of the
    variable 'val'. The name 'val' is out of scope during the whole time
    exit is doing its job, but the variable, now pointed to by 'ref', still
    exists. I think it is safe.

    > #include <stdio.h>
    > #include <stdlib.h>
    >
    > int *ref;
    >
    > void cleanup(void) {
    > if (ref) fprintf(stderr, "val = %d\n", *ref);
    > }
    >
    > void test(void) {
    > int val = 12;
    > ref = &val;
    > exit(EXIT_FAILURE);
    > }
    >
    > int main(void) {
    > atexit(cleanup);
    > test();
    > return 0;
    > }


    --
    Ben.
    Ben Bacarisse, Nov 15, 2007
    #2
    1. Advertising

  3. Laurent Deniau

    Richard Guest

    Ben Bacarisse <> writes:

    > Laurent Deniau <> writes:
    >
    >> I would like to know if the use of the pointer ref in the function
    >> cleanup() below is valid or if something in the norm prevents this
    >> kind of cross-reference during exit(). I haven't seen anything in the
    >> norm against this, I mean an as-if rule saying "atexit registered
    >> functions are executed as-if they were called from main", making val
    >> out of scope at this point.

    >
    > You don't mean scope. You are talking about the lifetime of the
    > variable 'val'. The name 'val' is out of scope during the whole time
    > exit is doing its job, but the variable, now pointed to by 'ref', still
    > exists. I think it is safe.
    >
    >> #include <stdio.h>
    >> #include <stdlib.h>
    >>
    >> int *ref;
    >>
    >> void cleanup(void) {
    >> if (ref) fprintf(stderr, "val = %d\n", *ref);
    >> }
    >>
    >> void test(void) {
    >> int val = 12;
    >> ref = &val;
    >> exit(EXIT_FAILURE);
    >> }


    I dont think it is safe.

    >>
    >> int main(void) {
    >> atexit(cleanup);
    >> test();


    test() runs but "int val" is effectively "gone" when the function exits.

    >> return 0;
    >> }


    At this point cleanup is called.

    Surely for this to be OK val would need to be a static?

    But, I welcome correction.
    Richard, Nov 15, 2007
    #3
  4. Laurent Deniau wrote:
    > I would like to know if the use of the pointer ref in the function
    > cleanup() below is valid or if something in the norm prevents this
    > kind of cross-reference during exit(). I haven't seen anything in the
    > norm against this, I mean an as-if rule saying "atexit registered
    > functions are executed as-if they were called from main", making val
    > out of scope at this point.
    >
    > a+, ld.
    >
    > #include <stdio.h>
    > #include <stdlib.h>
    >
    > int *ref;
    >
    > void cleanup(void) {
    > if (ref) fprintf(stderr, "val = %d\n", *ref);


    This test doesn't make sense if it is at all possible that ref is
    uninitialised. In this program, it's fine, but consider initialising ref
    to NULL at the start of main().

    > }
    >
    > void test(void) {
    > int val = 12;
    > ref = &val;
    > exit(EXIT_FAILURE);
    > }
    >
    > int main(void) {
    > atexit(cleanup);
    > test();
    > return 0;
    > }



    --
    Philip Potter pgp <at> doc.ic.ac.uk
    Philip Potter, Nov 15, 2007
    #4
  5. Richard <> writes:

    > Ben Bacarisse <> writes:
    >
    >> Laurent Deniau <> writes:
    >>
    >>> I would like to know if the use of the pointer ref in the function
    >>> cleanup() below is valid

    <snip>
    >> I think it is safe.
    >>
    >>> #include <stdio.h>
    >>> #include <stdlib.h>
    >>>
    >>> int *ref;
    >>>
    >>> void cleanup(void) {
    >>> if (ref) fprintf(stderr, "val = %d\n", *ref);
    >>> }
    >>>
    >>> void test(void) {
    >>> int val = 12;
    >>> ref = &val;
    >>> exit(EXIT_FAILURE);
    >>> }

    >
    > I dont think it is safe.
    >
    >>>
    >>> int main(void) {
    >>> atexit(cleanup);
    >>> test();

    >
    > test() runs but "int val" is effectively "gone" when the function
    > exits.


    but exit is called before test returns (in this context using the word
    'exit' for a function return in going to be a problem!). From my
    reading of the standard, the actions of exit -- i.e. the calling of
    all registered atexit functions -- take place like a normal function
    call. test() would return only after exit is done. I say "would"
    because this can happen only when exit returns to its caller -- and
    that does not happen (7.20.4.3 p6).

    >
    >>> return 0;
    >>> }

    >
    > At this point cleanup is called.


    No. You missed the call of exit in test().

    --
    Ben.
    Ben Bacarisse, Nov 15, 2007
    #5
  6. Laurent Deniau

    Richard Guest

    Ben Bacarisse <> writes:

    > No. You missed the call of exit in test().


    Quite correct!

    Is it "defined" that val is still there in this case?
    Richard, Nov 15, 2007
    #6
  7. Richard <> writes:

    > Ben Bacarisse <> writes:
    >
    >> No. You missed the call of exit in test().

    >
    > Quite correct!
    >
    > Is it "defined" that val is still there in this case?


    I can't see why not. If exit() were my_func() and my_func called the
    same functions that exit() does it certainly would be. I can't see any
    special case text that makes what exit() does special enough to
    invalidate this argument.

    --
    Ben.
    Ben Bacarisse, Nov 15, 2007
    #7
  8. Laurent Deniau

    Richard Guest

    Ben Bacarisse <> writes:

    > Richard <> writes:
    >
    >> Ben Bacarisse <> writes:
    >>
    >>> No. You missed the call of exit in test().

    >>
    >> Quite correct!
    >>
    >> Is it "defined" that val is still there in this case?

    >
    > I can't see why not. If exit() were my_func() and my_func called the
    > same functions that exit() does it certainly would be. I can't see any
    > special case text that makes what exit() does special enough to
    > invalidate this argument.


    Putting it that way I agree. I kind of had it in my mind that calling
    exit() was a bit more severe than my_function(). But thinking about it
    atoexit would be pretty useless if everything at global scope at least
    wasn't available, so why should the stack(!?) for test() have been
    folded. Interesting question though.
    Richard, Nov 15, 2007
    #8
  9. Laurent Deniau

    Flash Gordon Guest

    Philip Potter wrote, On 15/11/07 15:06:
    > Laurent Deniau wrote:
    >> I would like to know if the use of the pointer ref in the function
    >> cleanup() below is valid or if something in the norm prevents this
    >> kind of cross-reference during exit(). I haven't seen anything in the
    >> norm against this, I mean an as-if rule saying "atexit registered
    >> functions are executed as-if they were called from main", making val
    >> out of scope at this point.
    >>
    >> a+, ld.
    >>
    >> #include <stdio.h>
    >> #include <stdlib.h>
    >>
    >> int *ref;
    >>
    >> void cleanup(void) {
    >> if (ref) fprintf(stderr, "val = %d\n", *ref);

    >
    > This test doesn't make sense if it is at all possible that ref is
    > uninitialised. In this program, it's fine, but consider initialising ref
    > to NULL at the start of main().


    <snip>

    Not required. Any variable defined at file scope or defined as static in
    block scope is initialised to an appropriate zero if no initialisation
    is provided, so ref is initialised to a null pointer.
    --
    Flash Gordon
    Flash Gordon, Nov 15, 2007
    #9
  10. Laurent Deniau

    Eric Sosman Guest

    Ben Bacarisse wrote On 11/15/07 11:36,:
    > Richard <> writes:
    >
    >
    >>Ben Bacarisse <> writes:
    >>
    >>
    >>>No. You missed the call of exit in test().

    >>
    >>Quite correct!
    >>
    >>Is it "defined" that val is still there in this case?

    >
    >
    > I can't see why not. If exit() were my_func() and my_func called the
    > same functions that exit() does it certainly would be. I can't see any
    > special case text that makes what exit() does special enough to
    > invalidate this argument.


    A possible implementation of exit():

    #include <stdlib.h>
    #include <setjmp.h>
    #include "_implementation_magic.h"
    void exit(int code) {
    _exit_status = code;
    longjmp (_pre_main_jmpbuf, 1);
    }

    .... and Boom! all the program's `auto' variables vanish.
    Any atexit-registered functions had better not try to
    use them ...

    I don't know off-hand whether any implementations'
    exit() functions work this way, but I don't see anything
    in the Standard that would forbid it. So I, for one,
    will not make use of possibly-deceased `auto' variables
    in my atexit() functions, and I'd urge the same course
    on others.

    --
    Eric Sosman, Nov 15, 2007
    #10
  11. Eric Sosman <> writes:

    > Ben Bacarisse wrote On 11/15/07 11:36,:
    >> Richard <> writes:
    >>
    >>
    >>>Ben Bacarisse <> writes:
    >>>
    >>>
    >>>>No. You missed the call of exit in test().
    >>>
    >>>Quite correct!
    >>>
    >>>Is it "defined" that val is still there in this case?

    >>
    >>
    >> I can't see why not. If exit() were my_func() and my_func called the
    >> same functions that exit() does it certainly would be. I can't see any
    >> special case text that makes what exit() does special enough to
    >> invalidate this argument.

    >
    > A possible implementation of exit():
    >
    > #include <stdlib.h>
    > #include <setjmp.h>
    > #include "_implementation_magic.h"
    > void exit(int code) {
    > _exit_status = code;
    > longjmp (_pre_main_jmpbuf, 1);
    > }
    >
    > ... and Boom! all the program's `auto' variables vanish.
    > Any atexit-registered functions had better not try to
    > use them ...


    Hmmm... OK. But before I fold:

    My argument was based on the description of exit which has the rather
    suggestive phrase: "First, all functions registered by the atexit
    function are called". It can't see how it can do anything of
    significance before it does what it must do "first". Is that reading
    too much into the operational description of its actions?

    > I don't know off-hand whether any implementations'
    > exit() functions work this way, but I don't see anything
    > in the Standard that would forbid it. So I, for one,
    > will not make use of possibly-deceased `auto' variables
    > in my atexit() functions, and I'd urge the same course
    > on others.


    I certainly would not promote the style! It is obviously very fragile
    even if I am right (and I am not so sure any more).

    --
    Ben.
    Ben Bacarisse, Nov 15, 2007
    #11
  12. Laurent Deniau

    Eric Sosman Guest

    Ben Bacarisse wrote On 11/15/07 17:43,:
    > Eric Sosman <> writes:
    >
    >
    >>Ben Bacarisse wrote On 11/15/07 11:36,:
    >>
    >>>Richard <> writes:
    >>>
    >>>
    >>>
    >>>>Ben Bacarisse <> writes:
    >>>>
    >>>>
    >>>>
    >>>>>No. You missed the call of exit in test().
    >>>>
    >>>>Quite correct!
    >>>>
    >>>>Is it "defined" that val is still there in this case?
    >>>
    >>>
    >>>I can't see why not. If exit() were my_func() and my_func called the
    >>>same functions that exit() does it certainly would be. I can't see any
    >>>special case text that makes what exit() does special enough to
    >>>invalidate this argument.

    >>
    >> A possible implementation of exit():
    >>
    >> #include <stdlib.h>
    >> #include <setjmp.h>
    >> #include "_implementation_magic.h"
    >> void exit(int code) {
    >> _exit_status = code;
    >> longjmp (_pre_main_jmpbuf, 1);
    >> }
    >>
    >>... and Boom! all the program's `auto' variables vanish.
    >>Any atexit-registered functions had better not try to
    >>use them ...

    >
    >
    > Hmmm... OK. But before I fold:
    >
    > My argument was based on the description of exit which has the rather
    > suggestive phrase: "First, all functions registered by the atexit
    > function are called". It can't see how it can do anything of
    > significance before it does what it must do "first". Is that reading
    > too much into the operational description of its actions?


    I think so (obviously ...). If "first" were taken
    absolutely literally, as in "The very first executable
    statement in exit() must be a call to the most recently
    registered atexit() function," that would appear to
    outlaw even an `if' to discover if any functions were
    registered!

    More realistically (perhaps) if exit() looked like

    void exit(int status) {
    _call_atexit_functions();
    fflush(NULL);
    _close_open_streams();
    _remove_tempfiles();
    _really_exit(status);
    }

    .... then the "first" thing exit() calls is not one of
    the exit handlers, but a helper function that in turn
    calls those handlers. If you think this implementation
    is conforming, then a longjmp() to somewhere else that
    does all the same things ought to be conforming, too.

    --
    Eric Sosman, Nov 15, 2007
    #12
  13. In article <1195165134.642116@news1nwk> writes:
    > Ben Bacarisse wrote On 11/15/07 11:36,:

    ....
    > > I can't see why not. If exit() were my_func() and my_func called the
    > > same functions that exit() does it certainly would be. I can't see any
    > > special case text that makes what exit() does special enough to
    > > invalidate this argument.

    >
    > A possible implementation of exit():
    >
    > #include <stdlib.h>
    > #include <setjmp.h>
    > #include "_implementation_magic.h"
    > void exit(int code) {
    > _exit_status = code;
    > longjmp (_pre_main_jmpbuf, 1);
    > }
    >
    > ... and Boom! all the program's `auto' variables vanish.
    > Any atexit-registered functions had better not try to
    > use them ...


    7.20.4.3.2: First, all functions registered by the atexit function are
    called, in reverse order of their registration.

    The above implemetation does not conform to this.
    --
    dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
    home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
    Dik T. Winter, Nov 15, 2007
    #13
  14. Eric Sosman <> writes:

    > Ben Bacarisse wrote On 11/15/07 17:43,:
    >> Eric Sosman <> writes:

    <snip>
    >>> A possible implementation of exit():
    >>>
    >>> #include <stdlib.h>
    >>> #include <setjmp.h>
    >>> #include "_implementation_magic.h"
    >>> void exit(int code) {
    >>> _exit_status = code;
    >>> longjmp (_pre_main_jmpbuf, 1);
    >>> }
    >>>
    >>>... and Boom! all the program's `auto' variables vanish.
    >>>Any atexit-registered functions had better not try to
    >>>use them ...

    >>
    >>
    >> Hmmm... OK. But before I fold:
    >>
    >> My argument was based on the description of exit which has the rather
    >> suggestive phrase: "First, all functions registered by the atexit
    >> function are called". It can't see how it can do anything of
    >> significance before it does what it must do "first". Is that reading
    >> too much into the operational description of its actions?

    >
    > I think so (obviously ...). If "first" were taken
    > absolutely literally, as in "The very first executable
    > statement in exit() must be a call to the most recently
    > registered atexit() function," that would appear to
    > outlaw even an `if' to discover if any functions were
    > registered!


    Come now, I said "do anything of significance"!

    > More realistically (perhaps) if exit() looked like
    >
    > void exit(int status) {
    > _call_atexit_functions();
    > fflush(NULL);
    > _close_open_streams();
    > _remove_tempfiles();
    > _really_exit(status);
    > }
    >
    > ... then the "first" thing exit() calls is not one of
    > the exit handlers, but a helper function that in turn
    > calls those handlers. If you think this implementation
    > is conforming, then a longjmp() to somewhere else that
    > does all the same things ought to be conforming, too.


    I think if the atexit functions are permitted to be run after
    destroying all local variables it deserves a mention, so I am arguing
    partly from the significance of an omission.

    A final shot: C99 has VLAs, and I would have thought it at least
    possible that "rescuing" their contents in an atexit function is
    supposed to be allowed. Not a style I'd advocate, but pointing to a
    big VLA just before calling a function that might call exit (maybe a
    really badly written library function) is a use-case that needs to be
    clarified.

    --
    Ben.
    Ben Bacarisse, Nov 16, 2007
    #14
  15. Laurent Deniau

    Eric Sosman Guest

    Dik T. Winter wrote:
    > In article <1195165134.642116@news1nwk> writes:
    > > Ben Bacarisse wrote On 11/15/07 11:36,:

    > ...
    > > > I can't see why not. If exit() were my_func() and my_func called the
    > > > same functions that exit() does it certainly would be. I can't see any
    > > > special case text that makes what exit() does special enough to
    > > > invalidate this argument.

    > >
    > > A possible implementation of exit():
    > >
    > > #include <stdlib.h>
    > > #include <setjmp.h>
    > > #include "_implementation_magic.h"
    > > void exit(int code) {
    > > _exit_status = code;
    > > longjmp (_pre_main_jmpbuf, 1);
    > > }
    > >
    > > ... and Boom! all the program's `auto' variables vanish.
    > > Any atexit-registered functions had better not try to
    > > use them ...

    >
    > 7.20.4.3.2: First, all functions registered by the atexit function are
    > called, in reverse order of their registration.
    >
    > The above implemetation does not conform to this.


    Not sure what your objection is. It might be the meaning
    of "first," as in Ben Bacarisse's discussion, in which case I
    don't think c.l.c. is likely to arrive at any definitive answer.
    But if (and I'm only guessing) you imagine that this exit() would
    somehow fail to run the atexit() functions, my answer is that
    they could be "called"[*] from the pre-main() code to which the
    longjmp() returns:

    switch (setjmp(_pre_main_jmpbuf)) {
    case 0: /* first attempt */
    _exit_status = main(argc, argv);
    /* drop through */
    case 1: /* exit() called */
    _run_atexit_functions();
    fflush(NULL);
    _close_all_streams();
    _remove_tempfiles();
    /* drop through */
    case 2: /* _Exit() called */
    _really_exit(_exit_status);
    }

    [*] Please, no quibbles about whether "called" can be used
    in connection with code that might not be written in C.

    --
    Eric Sosman
    lid
    Eric Sosman, Nov 16, 2007
    #15
  16. Laurent Deniau

    Jack Klein Guest

    On Thu, 15 Nov 2007 17:18:53 -0500, Eric Sosman <>
    wrote in comp.lang.c:

    > Ben Bacarisse wrote On 11/15/07 11:36,:
    > > Richard <> writes:
    > >
    > >
    > >>Ben Bacarisse <> writes:
    > >>
    > >>
    > >>>No. You missed the call of exit in test().
    > >>
    > >>Quite correct!
    > >>
    > >>Is it "defined" that val is still there in this case?

    > >
    > >
    > > I can't see why not. If exit() were my_func() and my_func called the
    > > same functions that exit() does it certainly would be. I can't see any
    > > special case text that makes what exit() does special enough to
    > > invalidate this argument.

    >
    > A possible implementation of exit():
    >
    > #include <stdlib.h>
    > #include <setjmp.h>
    > #include "_implementation_magic.h"
    > void exit(int code) {
    > _exit_status = code;
    > longjmp (_pre_main_jmpbuf, 1);
    > }
    >
    > ... and Boom! all the program's `auto' variables vanish.
    > Any atexit-registered functions had better not try to
    > use them ...


    Such an implementation would not be standard conforming. Footnote 10
    attached to 5.1.2.3 specifically points out that automatic variables
    in main() still exist when if main() calls exit(). It refers to
    6.2.4, where paragraph 6 specifically states about automatic objects,
    "For such an object that does have a variable length array type, its
    lifetime extends from the declaration of the object until execution of
    the program leaves the scope of the declaration."

    A call to a function, including exit(), does not leave the scope of
    objects defined in the calling function.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://c-faq.com/
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
    Jack Klein, Nov 16, 2007
    #16
  17. On 16 nov, 04:07, Eric Sosman <> wrote:
    > Dik T. Winter wrote:
    > > In article <1195165134.642116@news1nwk> writes:
    > > > Ben Bacarisse wrote On 11/15/07 11:36,:

    > > ...
    > > > > I can't see why not. If exit() were my_func() and my_func called the
    > > > > same functions that exit() does it certainly would be. I can't see any
    > > > > special case text that makes what exit() does special enough to
    > > > > invalidate this argument.

    >
    > > > A possible implementation of exit():

    >
    > > > #include <stdlib.h>
    > > > #include <setjmp.h>
    > > > #include "_implementation_magic.h"
    > > > void exit(int code) {
    > > > _exit_status = code;
    > > > longjmp (_pre_main_jmpbuf, 1);
    > > > }

    >
    > > > ... and Boom! all the program's `auto' variables vanish.
    > > > Any atexit-registered functions had better not try to
    > > > use them ...

    >
    > > 7.20.4.3.2: First, all functions registered by the atexit function are
    > > called, in reverse order of their registration.

    >
    > > The above implemetation does not conform to this.

    >
    > Not sure what your objection is. It might be the meaning
    > of "first," as in Ben Bacarisse's discussion, in which case I
    > don't think c.l.c. is likely to arrive at any definitive answer.
    > But if (and I'm only guessing) you imagine that this exit() would
    > somehow fail to run the atexit() functions, my answer is that
    > they could be "called"[*] from the pre-main() code to which the
    > longjmp() returns:
    >
    > switch (setjmp(_pre_main_jmpbuf)) {
    > case 0: /* first attempt */
    > _exit_status = main(argc, argv);
    > /* drop through */
    > case 1: /* exit() called */
    > _run_atexit_functions();
    > fflush(NULL);
    > _close_all_streams();
    > _remove_tempfiles();
    > /* drop through */
    > case 2: /* _Exit() called */
    > _really_exit(_exit_status);
    > }


    This is exactly what I had in mind with my question. Unfortunately,
    the norm seems to says nothing explicit about this possible
    implementation and it seems to be very hard to detect automatically
    this behavior at runtime. Still, this implementation can be considered
    as an awkward case in the absence of explicit information, therefore I
    guess that it is not what the norm means/expects. No information on a
    point should mean "follow common sens", not "as tricky as possible".

    Nevertheless, adding a word about this point in the next release of
    the norm would be nice, as far as it doesn't break any existing
    implementation (e.g. one doing something like your code).

    a+, ld.
    Laurent Deniau, Nov 16, 2007
    #17
  18. On 15 nov, 23:43, Ben Bacarisse <> wrote:
    > Eric Sosman <> writes:
    > > Ben Bacarisse wrote On 11/15/07 11:36,:
    > >> Richard <> writes:

    >
    > >>>Ben Bacarisse <> writes:

    >
    > >>>>No. You missed the call of exit in test().

    >
    > >>>Quite correct!

    >
    > >>>Is it "defined" that val is still there in this case?

    >
    > >> I can't see why not. If exit() were my_func() and my_func called the
    > >> same functions that exit() does it certainly would be. I can't see any
    > >> special case text that makes what exit() does special enough to
    > >> invalidate this argument.

    >
    > > A possible implementation of exit():

    >
    > > #include <stdlib.h>
    > > #include <setjmp.h>
    > > #include "_implementation_magic.h"
    > > void exit(int code) {
    > > _exit_status = code;
    > > longjmp (_pre_main_jmpbuf, 1);
    > > }

    >
    > > ... and Boom! all the program's `auto' variables vanish.
    > > Any atexit-registered functions had better not try to
    > > use them ...

    >
    > Hmmm... OK. But before I fold:
    >
    > My argument was based on the description of exit which has the rather
    > suggestive phrase: "First, all functions registered by the atexit
    > function are called". It can't see how it can do anything of
    > significance before it does what it must do "first". Is that reading
    > too much into the operational description of its actions?
    >
    > > I don't know off-hand whether any implementations'
    > > exit() functions work this way, but I don't see anything
    > > in the Standard that would forbid it. So I, for one,
    > > will not make use of possibly-deceased `auto' variables
    > > in my atexit() functions, and I'd urge the same course
    > > on others.

    >
    > I certainly would not promote the style! It is obviously very fragile
    > even if I am right (and I am not so sure any more).


    I am not talking to promote this style, but there is cases where this
    is required like in "stack unwinding a-la-C++". You have a global
    pointer pointing to a linked list of "stacked" pointers to automatic
    variables holding critical resources and a proper implementation
    should call their destructor before exit()ing. I am open to any
    alternative, but the problem is not obvious.

    In fact, either C assumes that files are the only critical resource
    which need to be cleanup before exit()ing, either the implementation
    exibited by E. Sosman is not allowed. I cannot believe that the former
    is the intend of the norm.

    a+, ld.
    Laurent Deniau, Nov 16, 2007
    #18
  19. Laurent Deniau

    Eric Sosman Guest

    Jack Klein wrote:
    > On Thu, 15 Nov 2007 17:18:53 -0500, Eric Sosman <>
    > wrote in comp.lang.c:
    >> [... exit() might longjmp() to the caller of main() ...]

    >
    > Such an implementation would not be standard conforming. Footnote 10
    > attached to 5.1.2.3 specifically points out that automatic variables
    > in main() still exist when if main() calls exit(). It refers to
    > 6.2.4, where paragraph 6 specifically states about automatic objects,
    > "For such an object that does have a variable length array type, its
    > lifetime extends from the declaration of the object until execution of
    > the program leaves the scope of the declaration."


    Thanks for pointing out the footnote (on 5.1.2.2.3, by the way).
    Now it's *my* turn to cavil like a Philadelphia lawyer, taking
    cowardly refuge behind the "footnotes are non-normative" parapet.
    An exit() that obeys the intent expressed in the footnote could
    not operate as I suggested, and if it follows that intent then
    Laurent Deniau's original code is fine. Scary, but fine.

    > A call to a function, including exit(), does not leave the scope of
    > objects defined in the calling function.


    What about a call to the longjmp() function itself?

    --
    Eric Sosman
    lid
    Eric Sosman, Nov 16, 2007
    #19
  20. In article <> Eric Sosman <> writes:
    > Dik T. Winter wrote:

    ....
    > > > A possible implementation of exit():
    > > >
    > > > #include <stdlib.h>
    > > > #include <setjmp.h>
    > > > #include "_implementation_magic.h"
    > > > void exit(int code) {
    > > > _exit_status = code;
    > > > longjmp (_pre_main_jmpbuf, 1);
    > > > }
    > > >
    > > > ... and Boom! all the program's `auto' variables vanish.
    > > > Any atexit-registered functions had better not try to
    > > > use them ...

    > >
    > > 7.20.4.3.2: First, all functions registered by the atexit function are
    > > called, in reverse order of their registration.
    > >
    > > The above implemetation does not conform to this.

    >
    > Not sure what your objection is. It might be the meaning
    > of "first," as in Ben Bacarisse's discussion, in which case I
    > don't think c.l.c. is likely to arrive at any definitive answer.
    > But if (and I'm only guessing) you imagine that this exit() would
    > somehow fail to run the atexit() functions, my answer is that
    > they could be "called"[*] from the pre-main() code to which the
    > longjmp() returns:


    No. My objection is that the discussion is about "exit" as a function.
    The operations it has to do have to be done in the context where the
    function is called. It is only at the end where it is stated the the
    function goes out of context. Or would you contend that each function
    is allowed to first go out of context, only to restore the context
    when returning? In that case passing pointers to local variables to
    functions would be bad practice.
    --
    dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
    home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
    Dik T. Winter, Nov 16, 2007
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?U2FuZHk=?=

    Code to Exit Web App and Exit Internet Explorer

    =?Utf-8?B?U2FuZHk=?=, Aug 3, 2005, in forum: ASP .Net
    Replies:
    7
    Views:
    7,880
    =?Utf-8?B?U2FuZHk=?=
    Aug 5, 2005
  2. Joe Smith
    Replies:
    4
    Views:
    65,797
    sandeep1976
    Nov 8, 2006
  3. JKop
    Replies:
    8
    Views:
    449
  4. Replies:
    2
    Views:
    444
    Jeff Epler
    May 31, 2005
  5. Replies:
    3
    Views:
    290
    Gabriel Genellina
    Jul 13, 2007
Loading...

Share This Page