What happens if the return statement does not produce a return value in a function that produces a return value in C language? Does the compiler use garbage values in this case? Is this called undefined behavior?
For example;
#include <stdio.h>
int func() {
}
int main() {
int result = func();
printf("Result: %d\n", result);
return 0;
}
Output of this code : Result: 0
I am expecting this is a undefined behavior.
C 2018 6.9.1 12 says:
It is “otherwise specified” for the
mainfunction, because there are special rules for it in C 2018 5.1.2.2.3 1. For the functionfuncin the question, it is not otherwise specified. whenfuncis executed, program control reaches the}that terminatefunc. Then, in the caller,main, the return value offuncis used. Therefore, the behavior of this program is not defined by the C standard.If a called function and a calling function are compiled in separate source files and there is no extra communication between the object modules, such as link-time optimization information, then the compiler cannot see, when compiling the calling function, that the called function does not return a value. So the compiler must generate instructions that work if the function does return a value. In this case, the calling routine expects the function to return a value, so the instructions in it will fetch the value from the place where a value should be returned, usually a processor register designated for that purpose.
In the case in the question, with the functions in the same source file, the compiler can see there is undefined behavior. When compiling with optimization off, the compiler may act as described above. When optimization is on, a good compiler will see the code has undefined behavior. Then what happens depends on the design of the compiler. Likely behaviors include:
funcbut leave theprintf.In case 3, it might take out everything in
mainbut leave the return. That is not actually quite everything, since the return is left. I have seen a compiler actually remove everything inmain, leaving just an entry point with nothing to stop the code from continuing on into whatever is linked into memory after it.Case 2 can have some interesting effects. Without the undefined behavior, the normal sequence would be:
func.eax) used to return it to the register used to pass it toprintf(sayesi).printf.With undefined behavior in the code, the compiler might remove 1 and 2 but leave 3. In this case, the program will print the value in
esi, not the value ineax. That is, it will not print the value that was in the register used to return values; it will print the value in some other register. That is important to know when debugging—one way undefined behavior may manifest is by treating things as if they have values coming from unexpected places.