I’m having this weird problem which I can’t really figure our why this is happening.
Note: these programs are executed on centOS at the bash command line.
I have two similar C programs which are:
file1.c
#include <stdio.h>
int main()
{
int a, b;
printf("Enter two numsn");
scanf("%d %d", &a, &b);
printf("%d", a + b);
}
file2.c is the same as file1.c but in the second printf
line, it has n
at the end for the format string.
They are compiled using gcc file1.c
and gcc file2.c
.
From what I know, if a C program is executed successfully and without errors or a specific exit code using return(X), the program should return 0 thus exit code 0.
But for both files, when I’m running them (and entering 2 numbers to satisfy scanf
), I’m getting exit codes 2 and 3 respectively.
looking further for those codes, I found that exit code 2 means "Misuse of shell builtins" and I’m not sure why that is happening.
As for exit code 3, I didn’t find anything concrete, but since it’s not zero it indicates some kind of error, which again, I can’t seem to find errors in these short programs.
I’m entering the inputs using the keyboard. eg. ‘2[Enter]2[Enter]’
And checking the exit code using echo $?
right after running the programs (after they were compiled of course).
look something like this.
$ ./a.out
Enter two nums
2
2
4$
Important note: I can’t add ‘return 0’ in these programs, I’m getting them as a final product and later doing some manipulation with their output. So I can’t really change anything about these programs.
Would love your help regarding this issue. Thanks!
2
Answers
That warning you get means that you build with a very old version of GCC, at most version 4.9.4, which defaults to C90 standard compliant mode (with GCC extensions).
The implicit return from the
main
function was added in the C99 standard.Because there’s no return from the
main
function, you will have undefined behavior.There are three possible solutions:
main
function-std=c99
which tells the compiler to build according to the C99 standardThe C Standard makes a special case for the
main()
function and specifies that it implicitly returns0
in the absence of areturn
statement. This was added for C99 to try and work around the very common mistake and ensure a consistent exit code unless explicitly provided via areturn
statement or a call toexit()
.The compiler on your target system does not seem to comply with this rule and probably leaves the return value of the
printf
call in the register where the caller ofmain()
expects the return value. This is a tentative explanation, but before C99 the behavior was actually undefined, any exit status can be produced.If you enter
10
and20
,printf
outputs30
and returns2
, the number of bytes written tostdout
. If a newline is appended to the format string, the same input will produce 3 bytes, hence a return value of3
. On x86 systems, the return value ofprintf
is set in theax
,eax
orrax
register (in 16-, 32- and 64-bit modes). If this register is not changed before leaving themain
function, the startup code will assume that this value was set in themain
function and issue a system call to exit the program with this value as the exit code. The C startup behaves as ifmain()
was called asexit(main(argc, argv, envp))
.Adding a
return 0;
statement is the correct way to fix this problem. Upgrading the compiler should also fix it. It is actually very surprising that gcc would not add the implicitreturn 0;
, you must be using a very old version or a different compiler hiding behind the same command line (clang does this in macOS, but complies with the C99 standard).Regarding I found that exit code 2 means "Misuse of shell builtins": this is only a convention used by the shell for its own internal commands. The meaning of the exit status is a matter of convention and should be documented in the program’s manual page, but the actual exit status is just the return value of its
main
function, explicit or implicit or the argument to theexit()
call that terminated the program (or_exit()
,_Exit()
,quick_exit()
…)