'Returning a value from a function with no return [duplicate]
I think I have found a problem with the way functions are handled by the gcc compiler.
I don't know if it's a mistake or a never distraction on something I've let slip over the years. In practice, by declaring a function and defining the latter having a return value, the compiler stores the value of the first variable allocated in the range of the function in the EAX register, and then stores it, in turn, within a variable. Example:
#include<stdio.h>
int add(int a, int b)
{
int c = a + b;
;there isn't return
}
int main(void)
{
int res = add(3, 2);
return 0;
}
This is the output:
5
This is the x86-64 Assembly with intel syntax:
Function add:
push rbp
mov rbp, rsp
mov DWORD PTR[rbp-0x14], edi ;store first
mov DWORD PTR[rbp-0x18], esi ;store second
mov edx, DWORD PTR[rbp-0x14]
mov eax, DWORD PTR[rbp-0x18]
add eax, esx
mov DWORD PTR[rbp-0x4], eax
nop
pop rbp
ret
Function main:
push rbp
mov rbp, rsp
sub rsp, 0x10
mov esi, 0x2 ;first parameter
mov edi, 0x3 ;second parameter
call 0x1129 <add>
;WHAT??? eax = a + b, why store it?
mov DWORD PTR[rbp-0x4], eax
mov eax, 0x0
leave
ret
As you can see, it saves me the sum of the parameters a and b in the variable c, but then it saves me in the variable res the eax register containing their sum, as if a function returned values.
Is this done because the function was defined with a return value?
Solution 1:[1]
What you've done is trigger undefined behavior by failing to return a value from a function and then attempting to use that return value.
This is documented in section 6.9.1p12 of the C standard:
If the
}that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.
One of the ways that undefined behavior can manifest itself is by the program appearing to work properly, as you've seen. However, there's no guarantee that it will continue to work if for example, you added some unrelated code or compiled with different optimization settings.
Solution 2:[2]
eax is the register used to return a value, in this case because it is supposed to return int. So the caller gets whatever happens to be in that registers. However you should have gotten at least a warning, that there is no return statement.
Because your function is pretty small and the compiler decided to use the eax register for it's calculation, it appears to work.
If you switch on optimization or provide a more complex function, the result will be quite different.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | dbush |
| Solution 2 | Devolus |
