【问题标题】:C - GCC generates wrong instructions when returning local stack address [duplicate]C - GCC在返回本地堆栈地址时生成错误指令[重复]
【发布时间】: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 :(

标签: c gcc


【解决方案1】:

编译器生成了正确的指令。您所做的事情不是由 C 标准定义的,因此编译器可以随意做任何事情。在这种情况下,GCC 似乎很乐意返回一个空指针,可能是为了让您的程序尽快失败。

【讨论】:

  • 不是很令人满意的行为,它也可以按照它的指示去做但是没关系。
猜你喜欢
  • 2011-02-02
  • 2020-09-23
  • 2014-04-21
  • 2021-05-20
  • 2016-03-16
  • 1970-01-01
  • 2012-04-21
  • 2010-12-18
相关资源
最近更新 更多