Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > How can exit(n) give a function the return value?

Reply
Thread Tools

How can exit(n) give a function the return value?

 
 
pemo
Guest
Posts: n/a
 
      03-07-2006
Jordan Abel wrote:
> On 2006-03-07, Ian Collins <(E-Mail Removed)> wrote:
>> lovecreatesbeauty wrote:
>>> Hello experts,
>>>
>>> Is the following code snippet legal? If it is, how can exit() do the
>>> keyword return a favor and give a return value to the main function?
>>>
>>> Can a function call (or only this exit(n)) statement provide both
>>> function call and return features of the C programming language?
>>>
>>> /* headers omitted */
>>> int main (void)
>>> {
>>> exit(0); /* instead of `return 0;' */
>>> }
>>>

>> I guess _exit(0) is closer to return(0), exit does some clean-up
>> processing before terminating.

>
> So does return from main. The difference is in whether automatic
> variables declared in main are avaible to atexit handlers.


I read that initially as "automatic variables are available to atexit
handlers"

Wrong - right?


--
==============
*Not a pedant*
==============


 
Reply With Quote
 
 
 
 
Richard Bos
Guest
Posts: n/a
 
      03-07-2006
"pemo" <(E-Mail Removed)> wrote:

> Jordan Abel wrote:
> > On 2006-03-07, Ian Collins <(E-Mail Removed)> wrote:
> >> I guess _exit(0) is closer to return(0), exit does some clean-up
> >> processing before terminating.

> >
> > So does return from main. The difference is in whether automatic
> > variables declared in main are avaible to atexit handlers.

>
> I read that initially as "automatic variables are available to atexit
> handlers"
>
> Wrong - right?


And there's the rub.

If the program is ended through exit(), all auto objects in main() still
exist when the atexit handlers are called. One of the handlers could
refer to such an object - for example, if a global pointer had been set
to point at one of them.

If the program is ended through a return from main(), all auto objects
in main() will already have disappeared when the atexit handlers are
called. If a handler dereferences a pointer to such an ex-object, your
data could be pushing up the daisies.

Whether anyone sane will ever write an atexit handler that depends on
this difference - well, that's another question.

Richard
 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      03-07-2006
Richard Bos wrote:
>
> If the program is ended through a return from main(), all auto objects
> in main() will already have disappeared when the atexit handlers are
> called. If a handler dereferences a pointer to such an ex-object, your
> data could be pushing up the daisies.
>
> Whether anyone sane will ever write an atexit handler that depends on
> this difference - well, that's another question.


The problem can occur even without an explicit atexit()
handler:

int main(void) {
char buffer[16384];
setvbuf (stdout, buffer, _IOFBF, sizeof buffer);
...
return 0; /* woops! */
}

--
Eric Sosman
http://www.velocityreviews.com/forums/(E-Mail Removed)lid
 
Reply With Quote
 
Robin Haigh
Guest
Posts: n/a
 
      03-07-2006

"Richard Bos" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)4all.nl...
> "pemo" <(E-Mail Removed)> wrote:
>
> > Jordan Abel wrote:
> > > On 2006-03-07, Ian Collins <(E-Mail Removed)> wrote:
> > >> I guess _exit(0) is closer to return(0), exit does some clean-up
> > >> processing before terminating.
> > >
> > > So does return from main. The difference is in whether automatic
> > > variables declared in main are avaible to atexit handlers.

> >
> > I read that initially as "automatic variables are available to atexit
> > handlers"
> >
> > Wrong - right?

>
> And there's the rub.
>
> If the program is ended through exit(), all auto objects in main() still
> exist when the atexit handlers are called. One of the handlers could
> refer to such an object - for example, if a global pointer had been set
> to point at one of them.
>
> If the program is ended through a return from main(), all auto objects
> in main() will already have disappeared when the atexit handlers are
> called. If a handler dereferences a pointer to such an ex-object, your
> data could be pushing up the daisies.
>
> Whether anyone sane will ever write an atexit handler that depends on
> this difference - well, that's another question.



I can see people doing this:

#include <stdlib.h>

char **pa;

void cleanup(void) {
int i;
for ( i=0 ; i<10 ; i++ )
free(pa[i]);
}

int main(void){
int i;
char *a[10];
for ( i=0 ; i<10 ; i++ ) {
a[i] = malloc(whatever);
}
pa = a;
atexit(cleanup);
/* etc */
}

You aren't going to see what's wrong with this unless you've heard about the
issue. I certainly wouldn't call it insane. It's a nasty little trap.

One way to steer cleer of it is always to terminate using exit and never
return from main (though of course that leaves a hostage to fortune for
future maintenance)

--
RSH


 
Reply With Quote
 
lovecreatesbeauty
Guest
Posts: n/a
 
      03-07-2006

Peter Nilsson wrote:
> lovecreatesbeauty wrote:
> > ... in my sample code int main(); requires a return value,

>
> main() never _requires_ a return value. [Actually, there is one
> exception in that if main is being called recursively in C90, and the calling
> function uses the return value, then the behaviour is undefined.]
>


Perhaps I did not make it clear in my reply, sorry to bring this
misunderstanding. I do not know whether the entry point function main
needs a return value or not up to now. But I meant the prototype:

int main();

indicated that the function call expression had a value. There was no
return statement inside the function body. In my original post, there
is only one exit(0) call inside the function body. So how can the
semantics of the prototype be fulfilled?

I can understand this one: void f1(void) { exit(0); }
I can not understand this one: int f2(void) { exit(0); }

I read Richard Tobin's reply and I think I understand it. In my
original sample code, the int main(); function does not return, and it
does not mind whether it get a return value. As well as the discard of
the return value of a function like int main();, no return value is not
illegal. Do I understand it correct?

Thank all of you.

 
Reply With Quote
 
Ben Pfaff
Guest
Posts: n/a
 
      03-07-2006
Chris Torek <(E-Mail Removed)> writes:

> In article <(E-Mail Removed)>
> Ben Pfaff <(E-Mail Removed)> wrote:
>>... a more common implementation is that a return from main() causes
>>exit() to be returned.

>
> Presumably you mean "causes exit() to be called" here:


Yes, thank you for the correction.
--
"I don't have C&V for that handy, but I've got Dan Pop."
--E. Gibbons
 
Reply With Quote
 
Robin Haigh
Guest
Posts: n/a
 
      03-07-2006

"lovecreatesbeauty" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) ups.com...
>
> Peter Nilsson wrote:
> > lovecreatesbeauty wrote:
> > > ... in my sample code int main(); requires a return value,

> >
> > main() never _requires_ a return value. [Actually, there is one
> > exception in that if main is being called recursively in C90, and the

calling
> > function uses the return value, then the behaviour is undefined.]
> >

>
> Perhaps I did not make it clear in my reply, sorry to bring this
> misunderstanding. I do not know whether the entry point function main
> needs a return value or not up to now. But I meant the prototype:
>
> int main();
>
> indicated that the function call expression had a value. There was no
> return statement inside the function body. In my original post, there
> is only one exit(0) call inside the function body. So how can the
> semantics of the prototype be fulfilled?
>
> I can understand this one: void f1(void) { exit(0); }
> I can not understand this one: int f2(void) { exit(0); }
>
> I read Richard Tobin's reply and I think I understand it. In my
> original sample code, the int main(); function does not return, and it
> does not mind whether it get a return value. As well as the discard of
> the return value of a function like int main();, no return value is not
> illegal. Do I understand it correct?


Yes. In general, the flow of control in a program depends on the input
data, and can't be determined at compile time.(*) So there isn't much point
in requiring that an int function must contain a return statement, because
you can't tell whether any of the return statements will ever be reached.

At run time, only the statements executed matter.

(*) In fact some algorithms have theoretically unknown behaviour even
without any input data

--
RSH



 
Reply With Quote
 
Jordan Abel
Guest
Posts: n/a
 
      03-07-2006
On 2006-03-07, lovecreatesbeauty <(E-Mail Removed)> wrote:
>
> Peter Nilsson wrote:
>> lovecreatesbeauty wrote:
>> > ... in my sample code int main(); requires a return value,

>>
>> main() never _requires_ a return value. [Actually, there is one
>> exception in that if main is being called recursively in C90, and the calling
>> function uses the return value, then the behaviour is undefined.]
>>

>
> Perhaps I did not make it clear in my reply, sorry to bring this
> misunderstanding. I do not know whether the entry point function main
> needs a return value or not up to now. But I meant the prototype:
>
> int main();
>
> indicated that the function call expression had a value. There was no
> return statement inside the function body. In my original post, there
> is only one exit(0) call inside the function body. So how can the
> semantics of the prototype be fulfilled?


Some of the people in this group have radical ideas about the semantics
of main() in particular. I think Peter Nilsson's claim (which I disagree
with) is that even without an exit statement, main doesn't need to
return a value, since main's caller is outside the scope of the C
standard.

> I can understand this one: void f1(void) { exit(0); }
> I can not understand this one: int f2(void) { exit(0); }


Well - funny you ask. Due to yet another K&R holdover, int functions
don't have to return a value - "return;" or reaching the final right
brace is valid. However, the "returned value" cannot be used by any
caller.

>
> I read Richard Tobin's reply and I think I understand it. In my
> original sample code, the int main(); function does not return, and it
> does not mind whether it get a return value. As well as the discard of
> the return value of a function like int main();, no return value is
> not illegal. Do I understand it correct?
>
> Thank all of you.
>

 
Reply With Quote
 
Ben Pfaff
Guest
Posts: n/a
 
      03-07-2006
Jordan Abel <(E-Mail Removed)> writes:

> Due to yet another K&R holdover, int functions don't have to
> return a value - "return;" or reaching the final right brace is
> valid.


"return;" in a function returning int is no longer allowed in
C99:

6.8.6.4 The return statement
Constraints

1 A return statement with an expression shall not appear in a
function whose return type is void. A return statement
without an expression shall only appear in a function whose
return type is void.

--
"You call this a *C* question? What the hell are you smoking?" --Kaz
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      03-07-2006
"Robin Haigh" <(E-Mail Removed)> writes:
[...]
> Yes. In general, the flow of control in a program depends on the input
> data, and can't be determined at compile time.(*) So there isn't much point
> in requiring that an int function must contain a return statement, because
> you can't tell whether any of the return statements will ever be reached.

[...]

Theoretically, the language could require that there be a return
statement along all possible execution paths. For example:

int foo(void)
{
if (something) {
/* A */
}
else {
/* B */
}
/* C */
}

If there's a return statement at C, *or* if there are return
statements at both A and B, then one of them will always be executed;
otherwise the compiler can't prove that foo() can never reach the
closing brace without executing a return. (There are cases where a
function will never reach the closing brace but the compiler can't
prove it.)

Some compilers do this analysis and issue a warning such as "control
reaches end of non-void function". With some effort, the standard
could require all compilers to do this analysis, and make it a
constraint violation if the check fails. (I'm not necessariliy
advocating such change in the standard, just saying that it would be
possible.)

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
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: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
GIVE ME FILM OR GIVE ME DEATH l#vfgsgEg@AO1.com DVD Video 4 07-14-2005 03:10 PM
Give us 3 minutes; we give you the whole library lib Computer Support 1 02-04-2005 03:16 AM
Give us 3 minutes; we give you the whole library lib Computer Support 0 01-27-2005 07:52 AM
write a function such that when ever i call this function in some other function .it should give me tha data type and value of calling function parameter komal C++ 6 01-25-2005 11:13 AM



Advertisments