This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: calling exit in response to an error shouldn't be an error...


On 2019/06/09 14:52, Zan Lynx wrote:
> I am not a GCC developer, just a regular user of C. But I have some 
> comments below:
>
> On 6/9/2019 3:21 PM, L A Walsh wrote:
>   
>> If I have a function returning NULL on error (including EOF).
>>
>> So the program calls exit if the function doesn't return
>> a non-zero value (func() || exit(1)).
>>
>> I have:
>>
>> --/tmp/ex.c--
>>
>> main() { char * buf[512];
>>      while (gets(buf) || exit(0)) puts(buf);
>> }
>>
>> -- compile w/:
>> gcc -fpermissive --no-warnings  -o /tmp/ex /tmp/ex.c
>>
>> Got:
>> /tmp/ex.c: In function ‘main’:
>> /tmp/ex.c:2:22: error: void value not ignored as it ought to be
>>    while (gets(buf) || exit(0) ) puts(buf);
>>                        ^~~~~~~
>>
>> I understand that the while is testing the value of exit
>> "when it returns", but since it doesn't, why flag an error
>> (if exit is part of C-standard?) but *especially*, why
>> not a warning, like a type mismatch or such?
>>     
>
> There is a slight misunderstanding of operators here. This is not while 
> testing the value of exit(0). This is the "||" operator. It needs a 
> value on *both* sides of || so it can evaluate them both and return a 
> boolean result. Your code has no value on the right-hand side so it's 
> meaningless.
>   
----
    Um, but '||' and '&&' provide short circuiting.  So in the case where
the first function is true, the 2nd won't be called.  If the 2nd is called
it is guaranteed by the C11(17) standard not to return, so there can never
be a need for a return value in C11, as the program will terminate before
the value could be needed.
>   
>> But this:
>>
>> --/tmp/ex2.c--
>>
>> main(){ char * buf[512];
>>    while (1) {
>>      fgets(buf) || exit(1);
>>      fputs(buf);
>>    }
>> }
>>
>> ---compile + output:
>>     
>>> gcc -fpermissive --no-warnings  -o /tmp/ex2 /tmp/ex2.c
>>>       
>> /tmp/ex2.c: In function ‘main’:
>> /tmp/ex2.c:4:18: error: void value not ignored as it ought to be
>>      fgets(buf) || exit(1);
>>                    ^~~~~~~
>>
>> Ultra confusing -- how is exit value used?  Isn't it thrown away?
>>     
>
> Same problem here.
>   
----
    But the result isn't needed and is clearly never used even if
'exit' didn't actually terminate the program.  I.e. if the user wrote:
"1 || 2;"

    I can't see a current C11 compiler even emitting any code for such, but
I could see it emit a warning for something that would likely be a
user-error even if it was permitted by the language.

> I haven't tested it but you might be able to make this work with a comma 
> operator like "while (gets(buf) || (exit(0), 1)) puts(buf);"
>
> Oh, and "gets" is no longer a function. It's not just deprecated. It's 
> *gone*.
>   
---
    Still works though. In gcc 8.2.1 (which is said to be C18
compliant).  "gets" was said to be left in so that older programs
wouldn't suddenly fail over
something so widely used in examples (even though unsafe).

    I did contemplate including an equally safe workaround or at least a
getsn(buff,len), but resisted both urges as it wasn't the point of the
report.

   


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]