如果在返回值为int的函数里,漏掉return,会发生什么情况?
编译工具:Code::Blocks 10.05,代码如下所示
#include < cstdio >
int f()
{
}
int main ()
{
printf( " %d " ,f());
printf( " %d " ,f());
printf( " %d " ,f());
return 0 ;
}
In function 'int f()':|
warning: no return statement in function returning non-void|
但是能编译
Debug版本下结果如下:
1 2 2
Release版本下结果
0 0 0
下面分析一下为什么为发生这种情况:
从code:: blocks里面看到的 函数f的汇编代码
00401318
push
%
ebp
00401319 mov % esp, % ebp // 正确的似乎是 mov %ebp %esp
0040131B leave
0040131C ret
如果函数f()如下定义
00401319 mov % esp, % ebp // 正确的似乎是 mov %ebp %esp
0040131B leave
0040131C ret
int
f()
{
return 100 ;
}
则汇编代码是
{
return 100 ;
}
00401318
push
%
ebp
00401319 mov % esp, % ebp
0040131B mov $ 0x64 , % eax
00401320 leave
00401321 ret
接下来我们看一下整个main函数的汇编代码
00401319 mov % esp, % ebp
0040131B mov $ 0x64 , % eax
00401320 leave
00401321 ret
00401322
push
%
ebp
00401323 mov % esp, % ebp
00401325 and $ 0xfffffff0 , % esp
00401328 sub $ 0x10 , % esp
0040132B call 0x401770 < __main >
00401330 call 0x401318 < f() >
00401335 mov % eax, 0x4 ( % esp)
00401339 movl $ 0x403024 ,( % esp)
00401340 call 0x4019ac < printf >
00401345 call 0x401318 < f() >
0040134A mov % eax, 0x4 ( % esp) // 将返回值传递给%esp+0x04
0040134E movl $ 0x403024 ,( % esp)
00401355 call 0x4019ac < printf >
0040135A call 0x401318 < f() >
0040135F mov % eax, 0x4 ( % esp)
00401363 movl $ 0x403024 ,( % esp)
0040136A call 0x4019ac < printf >
0040136F mov $ 0x0 , % eax
00401374 leave
00401375 ret
00401323 mov % esp, % ebp
00401325 and $ 0xfffffff0 , % esp
00401328 sub $ 0x10 , % esp
0040132B call 0x401770 < __main >
00401330 call 0x401318 < f() >
00401335 mov % eax, 0x4 ( % esp)
00401339 movl $ 0x403024 ,( % esp)
00401340 call 0x4019ac < printf >
00401345 call 0x401318 < f() >
0040134A mov % eax, 0x4 ( % esp) // 将返回值传递给%esp+0x04
0040134E movl $ 0x403024 ,( % esp)
00401355 call 0x4019ac < printf >
0040135A call 0x401318 < f() >
0040135F mov % eax, 0x4 ( % esp)
00401363 movl $ 0x403024 ,( % esp)
0040136A call 0x4019ac < printf >
0040136F mov $ 0x0 , % eax
00401374 leave
00401375 ret
从中我们可以看出,函数f()是将返回值通过EAX寄存器中,传递给调用它的代码。
如过我们漏掉了return intVal语句,在Debug模式下可能会导致,调用f()的代码得到的是上次的其他函数被调用的返回值。
在进入main之后EAX通常会被初始化为0x01.所以第一个f() 返回值为1.
printf 打印了“1 ”两个字符之后,返回值为2,所以第二个f()返回值为2。
printf 打印了“2 ”两个字符之后,返回值为2,所以第三个f()返回值为2。
在Release版本下,函数f()被优化,printf直接打印数字0。
401320
: push
%
ebp
401321 : mov % esp, % ebp
401323 : and $ 0xfffffff0 , % esp
401326 : sub $ 0x10 , % esp
401329 : call 0x401760
40132e: movl $ 0x0 , 0x4 ( % esp)
401335 :
401336 : movl $ 0x403024 ,( % esp)
40133d: call 0x40199c
401342 : movl $ 0x0 , 0x4 ( % esp)
401349 :
40134a: movl $ 0x403024 ,( % esp)
401351 : call 0x40199c
401356 : movl $ 0x0 , 0x4 ( % esp)
40135d:
40135e: movl $ 0x403024 ,( % esp)
401365 : call 0x40199c
40136a: xor % eax, % eax
40136c: leave
40136d: ret
401321 : mov % esp, % ebp
401323 : and $ 0xfffffff0 , % esp
401326 : sub $ 0x10 , % esp
401329 : call 0x401760
40132e: movl $ 0x0 , 0x4 ( % esp)
401335 :
401336 : movl $ 0x403024 ,( % esp)
40133d: call 0x40199c
401342 : movl $ 0x0 , 0x4 ( % esp)
401349 :
40134a: movl $ 0x403024 ,( % esp)
401351 : call 0x40199c
401356 : movl $ 0x0 , 0x4 ( % esp)
40135d:
40135e: movl $ 0x403024 ,( % esp)
401365 : call 0x40199c
40136a: xor % eax, % eax
40136c: leave
40136d: ret