为什么gcc返回0而不是堆栈分配变量的地址? [英] Why does gcc return 0 instead of the address of a stack allocated variable?

查看:51
本文介绍了为什么gcc返回0而不是堆栈分配变量的地址?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为使用自定义堆栈的实验的一部分,我希望有一个函数返回堆栈分配的char缓冲区的地址.

 //返回指向堆栈变量的指针无效* foo(void){char sz [10] ="hello";返回sz;} 

我知道在C语言中执行此操作是非法的,并且gcc也发出警告.

  gcc -Wall -Wextra -pedantic -std = gnu99 -fomit-frame-pointer -O0 -c foo.cfoo.c:8:12:警告:函数返回本地变量[-Wreturn-local-addr]的地址返回sz; 

不过,由于这是实验的一部分,所以我希望原样编写代码.有趣的是,生成的代码返回0而不是sz的堆栈地址:

  boa @ localhost:〜/tmp $ objdump -dMintel foo.o0000000000000000< foo> ;:0:48 b8 68 65 6c 6c 6f movabs rax,0x6f6c6c65687:00 00 00一个:48 89 44 24 f0 mov QWORD PTR [rsp-0x10],raxf:66 c7 44 24 f8 00 00 mov WORD PTR [rsp-0x8],0x016:b8 00 00 00 00 mov eax,0x01b:c3 ret 

正如人们所看到的,0x0移到了eax上,这使我感到困惑.为什么gcc这样做?

这是一个完整的源文件,带有另一个函数bar()和一个主要函数.bar()返回预期的地址.

  #include< stdint.h>#include< stdio.h>//返回指向堆栈变量的指针无效* foo(void){char sz [10] ="hello";返回sz;}无效* bar(void){char sz [10] ="hello";intptr_t i =(intptr_t)sz;返回(void *)i;}int main(无效){printf("foo:%p \ n",foo());printf("bar:%p \ n",bar());返回0;}boa @ localhost:〜/tmp $ make foo&&./foocc foo.o -o foofoo :(无)条:0x7ffce518a268 

这对我来说是个谜.gcc选择背后的逻辑可能是什么?

I know that it's illegal to do this in C, and gcc warns too.

gcc -Wall -Wextra -pedantic -std=gnu99 -fomit-frame-pointer -O0 -c foo.c 

foo.c:8:12: warning: function returns address of local variable [-Wreturn-local-addr]
     return sz;

Still, since this is part of an experiment, I want the code as is. The funny thing is that the generated code returns 0 instead of sz's stack address:

boa@localhost:~/tmp$ objdump -dMintel foo.o
0000000000000000 <foo>:
   0:   48 b8 68 65 6c 6c 6f    movabs rax,0x6f6c6c6568
   7:   00 00 00 
   a:   48 89 44 24 f0          mov    QWORD PTR [rsp-0x10],rax
   f:   66 c7 44 24 f8 00 00    mov    WORD PTR [rsp-0x8],0x0
  16:   b8 00 00 00 00          mov    eax,0x0
  1b:   c3                      ret    

As one can see, 0x0 is moved to eax, which is what puzzles me. Why does gcc do this?

Here's a complete source file with another function, bar(), as well as a main function. bar() returns the address as expected.

#include <stdint.h>
#include <stdio.h>

// return pointer to stack variable
void *foo(void)
{
    char sz[10] = "hello";
    return sz;
}

void *bar(void)
{
    char sz[10] = "hello";
    intptr_t i = (intptr_t)sz;
    return (void*)i;
}

int main(void)
{
    printf("foo: %p\n", foo());
    printf("bar: %p\n", bar());
    return 0;
}

boa@localhost:~/tmp$ make foo && ./foo
cc   foo.o   -o foo
foo: (nil)
bar: 0x7ffce518a268

This is a mystery to me. What may be the logic behind gcc's choice?

解决方案

GCC deliberately returns NULL in this case as can be seen from the code:

tree zero = build_zero_cst (TREE_TYPE (val));
gimple_return_set_retval (return_stmt, zero);
update_stmt (stmt);

Newer versions of GCC and Clang exploit undefined behavior more aggressively so this check is not suprising. It also makes code fail fast which is a good thing in most cases (not yours, apparently).

这篇关于为什么gcc返回0而不是堆栈分配变量的地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆