【发布时间】:2016-05-01 14:37:19
【问题描述】:
当我编写一个函数时,GCC 生成了错误的指令 返回对局部变量的引用。我完全知道你不应该那样做。
这是简单的代码:
#include <stdio.h>
#include <stdlib.h>
int *func()
{
int a = 100;
return &a;
}
int main()
{
printf("%p\n", func());
}
程序的输出是“(nil)”。
我刚刚用“gcc sample.c”编译了这个并用gdb反汇编了可执行文件:
Dump of assembler code for function func:
0x00000000004004e6 <+0>: push %rbp
0x00000000004004e7 <+1>: mov %rsp,%rbp
0x00000000004004ea <+4>: movl $0x64,-0x4(%rbp)
0x00000000004004f1 <+11>: mov $0x0,%eax
0x00000000004004f6 <+16>: pop %rbp
0x00000000004004f7 <+17>: retq
End of assembler dump.
Dump of assembler code for function main:
0x00000000004004f8 <+0>: push %rbp
0x00000000004004f9 <+1>: mov %rsp,%rbp
0x00000000004004fc <+4>: mov $0x0,%eax
0x0000000000400501 <+9>: callq 0x4004e6 <func>
0x0000000000400506 <+14>: mov %rax,%rsi
0x0000000000400509 <+17>: mov $0x4005a4,%edi
0x000000000040050e <+22>: mov $0x0,%eax
0x0000000000400513 <+27>: callq 0x4003c0 <printf@plt>
0x0000000000400518 <+32>: mov $0x0,%eax
0x000000000040051d <+37>: pop %rbp
0x000000000040051e <+38>: retq
End of assembler dump.
如您所见,返回值为 0。它应该为 -0x4(%rbp)。 我没有找到任何可以解释的东西。我的猜测是 GCC 开发人员希望这段代码尽可能快地失败(空指针取消引用),但这不可能。编译器必须生成正确的指令。 我已经用 GCC 5.3.0 对此进行了测试。
【问题讨论】:
-
我认为对于这种情况没有存在正确的说明;这是导致未定义行为的行为,这意味着编译器可以生成它想要的任何指令。
-
指向不再存在的对象的指针具有不确定值。这里没有“正确”或“错误”的价值。这个不确定的值在你的实验中表现为一个空指针?没有错。
-
在我看来这仍然是“错误的”。如果程序员想要地址,那么他想要 address 但我知道它没有定义。这也是 not 重复的,因为我的问题是指生成的指令,而不是它未定义的事实。你为什么认为我写了“我完全知道你不应该那样做”?
-
'我想要定义未定义的行为'#00327690234 :(