Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > exit, atexit and scope

Reply
Thread Tools

exit, atexit and scope

 
 
Laurent Deniau
Guest
Posts: n/a
 
      11-15-2007
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;
}
 
Reply With Quote
 
 
 
 
Ben Bacarisse
Guest
Posts: n/a
 
      11-15-2007
Laurent Deniau <(E-Mail Removed)> 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.
 
Reply With Quote
 
 
 
 
Richard
Guest
Posts: n/a
 
      11-15-2007
Ben Bacarisse <(E-Mail Removed)> writes:

> Laurent Deniau <(E-Mail Removed)> 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.
 
Reply With Quote
 
Philip Potter
Guest
Posts: n/a
 
      11-15-2007
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
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      11-15-2007
Richard <(E-Mail Removed)> writes:

> Ben Bacarisse <(E-Mail Removed)> writes:
>
>> Laurent Deniau <(E-Mail Removed)> 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.
 
Reply With Quote
 
Richard
Guest
Posts: n/a
 
      11-15-2007
Ben Bacarisse <(E-Mail Removed)> writes:

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


Quite correct!

Is it "defined" that val is still there in this case?
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      11-15-2007
Richard <(E-Mail Removed)> writes:

> Ben Bacarisse <(E-Mail Removed)> 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.
 
Reply With Quote
 
Richard
Guest
Posts: n/a
 
      11-15-2007
Ben Bacarisse <(E-Mail Removed)> writes:

> Richard <(E-Mail Removed)> writes:
>
>> Ben Bacarisse <(E-Mail Removed)> 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.

 
Reply With Quote
 
Flash Gordon
Guest
Posts: n/a
 
      11-15-2007
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
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      11-15-2007
Ben Bacarisse wrote On 11/15/07 11:36,:
> Richard <(E-Mail Removed)> writes:
>
>
>>Ben Bacarisse <(E-Mail Removed)> 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.

--
http://www.velocityreviews.com/forums/(E-Mail Removed)
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Context manager, atexit processing, and PEP 3143DaemonContext.close Carl Banks Python 5 05-19-2009 10:22 PM
question about ctrl-d and atexit with threads Darren Dale Python 8 03-06-2009 06:46 PM
atexit problems and questions.... MathWizard C++ 9 07-29-2007 07:50 PM
atexit() and DLLs Andreas Schmitt C++ 1 03-09-2007 10:00 AM
atexit and global destructors Serve Laurijssen C++ 3 01-15-2004 05:52 PM



Advertisments