程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了返回局部变量地址的函数在不同版本的 gcc 中表现不同?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决返回局部变量地址的函数在不@R_722_11197@的 gcc 中表现不同??

开发过程中遇到返回局部变量地址的函数在不@R_722_11197@的 gcc 中表现不同?的问题如何解决?下面主要结合日常开发的经验,给出你关于返回局部变量地址的函数在不@R_722_11197@的 gcc 中表现不同?的解决方法建议,希望对你解决返回局部变量地址的函数在不@R_722_11197@的 gcc 中表现不同?有所启发或帮助;

我写了这段代码,发现它在不@R_722_11197@的 gcc 中表现不同。

源代码,

#include<stdio.h>

int *fun();

int main(int argc,char *argv[])
{
    int *ptr;

    ptr = fun();

    printf("%x",*ptr);
}

int *fun()
{
    int *ptr;
    int foo = 0xdeadbeef;
    ptr = &foo;

    return ptr;
}

代码有误。执行fun()后,局部变量foo被释放,不存在。但是@H_186_7@main函数试图使用它,因此会导致分段错误。

但我在三个版本的 gcc 上尝试了相同的代码,但它们的行为不同。

10.2.0

╭─    ~ ································································ ✔ ─╮
╰─ gcc -v | bin/pbcopy                                                            ─╯
Using built-in specs.
ColLECT_GCC=gcc
ColLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-BUGurl=https://BUGs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,Obj-C++,d --with-isl --with-linker-hash-style=gnu --with-system-zlib --enable-__cxa_atexit --enable-CET=auto --enable-checking=release --enable-clocale=gnu --enable-default-pIE --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-install-libiberty --enable-linker-build-ID --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-@R_751_4035@-exceptions --disable-werror gdc_include_dir=/usr/include/dlang/gdc
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 10.2.0 (GCC)


╭─    ~ ································································ ✔ ─╮
╰─ gcc a.c && a.out                                                               ─╯
deadbeef%                                                                            

它打印 deadbeef

它的汇编@R_801_11346@

(gdb) disassemble fun 
Dump of assembler code for function fun:
   0x000000000000119d <+23>:    movl   $0xdeadbeef,-0x14(%rbp)
   0x00000000000011a4 <+30>:    lea    -0x14(%rbp),%rax
   0x00000000000011a8 <+34>:    mov    %rax,-0x10(%rbp)
   0x00000000000011ac <+38>:    mov    -0x10(%rbp),%rax
   0x00000000000011b0 <+42>:    mov    -0x8(%rbp),%rdx
   0x00000000000011b4 <+46>:    sub    %fs:0x28,%rdx
   0x00000000000011bd <+55>:    je     0x11c4 <fun+62>
   0x00000000000011bf <+57>:    call   0x1030 <__stack_chk_fail@plt>
   0x00000000000011c4 <+62>:    leave  
   0x00000000000011c5 <+63>:    ret    
End of assembler dump.

(gdb) disass main

   0x000000000000116c <+35>:    mov    %eax,%esi
   0x000000000000116e <+37>:    lea    0xe8f(%rip),%rdi        # 0x2004
   0x0000000000001175 <+44>:    mov    $0x0,%eax
   0x000000000000117a <+49>:    call   0x1040 <printf@plt>

汇编代码显示函数将 0xdeadbeef 存储在 %rax 中,printf 将其接收为 %esi,因此打印 0xdeadbeef

在 9.3.0 中

coolder@ASUS:~$ gcc -v                                                          [1/1]
Using built-in specs.                                                                
ColLECT_GCC=gcc
ColLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper
OFFLOAD_TARGEt_nameS=nvptx-none:hsa
OFFLOAD_TARGET_DEFAulT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 9.3.0-15' --with-BUGurl=file:///usr/share/doc/gcc-9/README.bUGs --enable-languages=c,brig,d,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-ID --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-deBUG --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pIE --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-List=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-0xEOmg/gcc-9-9.3.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutexThread model: posix
gcc version 9.3.0 (Debian 9.3.0-15)


coolder@ASUS:~$ gcc a.c && ./a.out
a.c: In function ‘fun’:
a.c:14:9: warning: function returns address of local variable [-Wreturn-local-addr]
   14 |  return &a;
      |         ^~
0coolder@ASUS:~$ 

它打印了 0。

它的汇编代码,

(gdb) disassemble fun
Dump of assembler code for function fun:
   0x000055555555515e <+0>:     push   %rbp
   0x000055555555515f <+1>:     mov    %rsp,%rbp
   0x0000555555555162 <+4>:     movl   $0xdeadbeef,-0x4(%rbp)
   0x0000555555555169 <+11>:    mov    $0x0,%eax
   0x000055555555516e <+16>:    pop    %rbp
(gdb) disass main
   0x000055555555513e <+9>:     call   0x55555555515e <fun>
   0x0000555555555143 <+14>:    mov    %rax,%rsi
   0x0000555555555146 <+17>:    lea    0xeb7(%rip),%rdi        # 0x555555556004
   0x000055555555514d <+24>:    mov    $0x0,%eax

汇编代码显示它将 0 移动到 %eax,并且 printf 使用 %eax 作为 %rsi,因此它打印 0。>

在 5.4.1

➜  ~ gcc a.c && ./a.out 
a.c: In function ‘fun’:
a.c:17:9: warning: function returns address of local variable [-Wreturn-local-addr]
  return &a;
         ^
[1]    3566 segmentation fault (core dumped)  ./a.out

正如我所料,它出现分段错误。

它的汇编代码,

(gdb) disassemble fun 
Dump of assembler code for function fun:
   0x08048448 <+0>:     push   %ebp
   0x08048449 <+1>:     mov    %esp,%ebp
   0x0804844b <+3>:     sub    $0x10,%esp
   0x0804844e <+6>:     movl   $0xdeadbeef,-0x4(%ebp)
   0x08048455 <+13>:    mov    $0x0,%eax
   0x0804845a <+18>:    leave  
   0x0804845b <+19>:    ret   

(gdb) disass main
   0x0804841d <+17>:    call   0x8048448 <fun>
   0x08048422 <+22>:    mov    %eax,-0xc(%ebp)
   0x08048425 <+25>:    mov    -0xc(%ebp),%eax
   0x08048428 <+28>:    mov    (%eaX),%eax

汇编代码显示它将 0x0 移动到 %eax,并且 main 尝试引用 %eax,因此这会导致分段错误。

那么为什么汇编代码如此不同?

任何帮助将不胜感激。

解决方法

返回局部变量的地址并在其生命周期结束后尝试访问它是undefined behavior,合理化引擎盖下发生的事情是一个傻瓜的差事,因为没有可遵循的标准规则(部分,当然,根据上述和链接的 UB 规则),不同的编译器版本会改变处理此类情况的方式是很常见的。

大佬总结

以上是大佬教程为你收集整理的返回局部变量地址的函数在不同版本的 gcc 中表现不同?全部内容,希望文章能够帮你解决返回局部变量地址的函数在不同版本的 gcc 中表现不同?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:gcc