Home > Mobile >  Unexpected exit code (2 and 3) of c programs
Unexpected exit code (2 and 3) of c programs

Time:05-19

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 nums\n");
    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!

CodePudding user response:

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:

  1. Upgrade to a newer version of GCC (it's not up to 12.1) where it defaults to at least C99 mode.
  2. Modify the code to add an explicit return from the main function
  3. Build with the flag -std=c99 which tells the compiler to build according to the C99 standard

CodePudding user response:

The C Standard makes a special case for the main() function and specifies that it implicitly returns 0 in the absence of a return 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 a return statement or a call to exit().

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 of main() 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 and 20, printf outputs 30 and returns 2, the number of bytes written to stdout. If a newline is appended to the format string, the same input will produce 3 bytes, hence a return value of 3. On x86 systems, the return value of printf is set in the ax, eax or rax register (in 16-, 32- and 64-bit modes). If this register is not changed before leaving the main function, the startup code will assume that this value was set in the main function and issue a system call to exit the program with this value as the exit code. The C startup behaves as if main() was called as exit(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 implicit return 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 the exit() call that terminated the program (or _exit(), _Exit(), quick_exit()...)

  • Related