首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在这个简单的函数调用堆栈中发生了什么?

在这个简单的函数调用堆栈中发生了什么?
EN

Stack Overflow用户
提问于 2021-08-07 11:10:11
回答 1查看 121关注 0票数 1

假设我们有以下超级简单的prorgam ex.c

代码语言:javascript
复制
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void getpath()
{
  char buffer[8];
  gets(buffer);
}

int main(int argc, char **argv)
{
  getpath();
}

在返回main()函数之前,我希望在堆栈中看到的内容如下

代码语言:javascript
复制
buffer[0-3]
buffer[4-7]
SAVED_EBP
SAVED_EIP

相反,在SAVED_EBPbuffer之间总是有两个奇怪的地址-- xb7ec63000xb7ff1040 (参见下面的gdb()会话),我尝试使用不同的缓冲区长度,因为我认为这是编译器所做的某种填充的结果,然而,它们总是存在的。我的问题是?这些地址是什么,为什么总是被分配?

getpath()程序集:

代码语言:javascript
复制
(gdb) disass getpath
Dump of assembler code for function getpath:
0x080483c4 <getpath+0>:     push   ebp
0x080483c5 <getpath+1>:     mov    ebp,esp
0x080483c7 <getpath+3>:     sub    esp,0x28
0x080483ca <getpath+6>:     lea    eax,[ebp-0x10]
0x080483cd <getpath+9>:     mov    DWORD PTR [esp],eax
0x080483d0 <getpath+12>:    call   0x80482e8 <gets@plt>
0x080483d5 <getpath+17>:    leave  
0x080483d6 <getpath+18>:    ret    
End of assembler dump.

编译(gcc -o ex ex.c)后,在getpathleave指令处设置一个断点,并输入AAAAAAA

代码语言:javascript
复制
(gdb) x/12x $sp
0xbffffc80: 0xbffffc98  0x0804959c  0xbffffcb8  0x08048419
0xbffffc90: 0xb7fd8304  0xb7fd7ff4  0x41414141  0x00414141
0xbffffca0: 0xb7ec6365  0xb7ff1040  0xbffffcb8  0x080483e2

(gdb) x/1x 0xb7ec6365
0xb7ec6365 <__cxa_atexit+53>:   0x5b10c483

(gdb) x/1x 0xb7ff1040
0xb7ff1040 <_dl_fini>:  0x57e58955

(gdb) info frame
Stack level 0, frame at 0xbffffcb0:
 eip = 0x80483d5 in getpath; saved eip 0x80483e2
 called by frame at 0xbffffcc0
 Arglist at 0xbffffca8, args: 
 Locals at 0xbffffca8, Previous frame's sp is 0xbffffcb0
 Saved registers:
  ebp at 0xbffffca8, eip at 0xbffffcac

更新

谢谢丹尼尔·克莱恩斯坦!因此,很明显,我们可以看到,gets()是可响应的:

我编写了两个琐碎的程序,它们唯一的区别就是使用gets()

  • gets.c

#include # ## #include char getpath() { char buffer4;get(Buffer4);} int main(int argc,char **argv) { getpath();}

  • nogets.c

#include # ## #include void (){ char buffer4 ={65,65,65};} int main(int argc,char **argv) { getpath();}

然后,我们使用gdb运行这两个程序,并根据leave指令在getpath中设置一个breakpoint (和前面一样),使用x/12x $sp命令检查堆栈。

  • gets.c STACK FRAME

如您所见,0xb7ec63650xb7ff1040仍然存在。

  • nogets.c STACK FRAME

但是我找不到任何关于这个清理过程的文档,你知道我怎样才能挖掘得更深吗?

EN

回答 1

Stack Overflow用户

发布于 2021-08-08 06:48:13

我认为这是因为编译器做了某种填充,

实际上,它们只是编译器为保持堆栈32字节对齐而添加的填充。你可以用-mpreferred-stack-boundary=2处理掉它们。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68691847

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档