C-GCC在返回本地堆栈地址时生成错误的指令

C-GCC在返回本地堆栈地址时生成错误的指令,c,gcc,C,Gcc,当我编写一个函数时,GCC生成了错误的指令 返回对局部变量的引用。我很清楚你不应该那样做 下面是简单的代码: #include <stdio.h> #include <stdlib.h> int *func() { int a = 100; return &a; } int main() { printf("%p\n", func()); } #包括 #包括 int*func() { INTA=100; 回报&a; } int mai

当我编写一个函数时,GCC生成了错误的指令 返回对局部变量的引用。我很清楚你不应该那样做

下面是简单的代码:

#include <stdio.h>
#include <stdlib.h>

int *func()
{
    int a = 100;
    return &a;
}

int main()
{
    printf("%p\n", func());
}
#包括
#包括
int*func()
{
INTA=100;
回报&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.
函数func的汇编程序代码转储: 0x0000000000404E6:推送%rbp 0x00000000004004e7:mov%rsp,%rbp 0x000000000004004EA:movl$0x64,-0x4(%rbp) 0x0000000000404F1:mov$0x0,%eax 0x00000000004004f6:弹出%rbp 0x00000000004004f7:retq 汇编程序转储结束。 主功能的汇编程序代码转储: 0x00000000004004f8:推送%rbp 0x00000000004004f9:mov%rsp,%rbp 0x00000000004004fc:mov$0x0,%eax 0x0000000000400501:callq 0x4004e6 0x0000000000400506:mov%rax,%rsi 0x0000000000400509:mov$0x4005a4,%edi 0x000000000040050e:mov$0x0,%eax 0x0000000000400513:callq 0x4003c0 0x0000000000400518:mov$0x0,%eax 0x000000000040051d:弹出%rbp 0x000000000040051e:retq 汇编程序转储结束。 如您所见,返回值为0。它应该是-0x4(%rbp)。 我没发现这能解释什么。我的猜测是,GCC开发人员希望该代码尽可能快地失败(空指针解引用),但这不可能。编译器必须生成正确的指令。
我已经用GCC 5.3.0对此进行了测试。

编译器生成了正确的指令。您所做的不是由C标准定义的,因此编译器可以自由地做任何它喜欢的事情。在这种情况下,GCC似乎愿意返回空指针,这样您的程序可能会尽快失败。

我认为这种情况下没有正确的指令;这是一种导致未定义行为的行为,这意味着编译器可以生成它想要的任何指令。或者,指向不再存在的对象的指针的值是不确定的。这里没有“对”或“错”的值。这个不确定的值在您的实验中显示为空指针?没什么问题。在我看来这仍然是“错误的”。如果程序员想要这个地址,那么他想要这个地址,但我知道它没有定义。此外,这不是重复的,因为我的问题是指生成的指令,而不是它没有定义的事实。为什么你认为我写了“我完全知道你不应该那样做”?“我想要定义未定义的行为”#00327690234:(不是很令人满意的行为,它也可以做它被要求做的事,但还好。