【发布时间】:2022-01-20 14:35:37
【问题描述】:
我试图通过一些实际示例来了解函数的调用堆栈。在所有解释这一点的图表中,它的布局类似于 [局部变量][返回地址][参数](左侧内存不足)。但是当我在 gdb 中并在函数中设置断点时,我会以不同的顺序获取它们:
(gdb) info args
arg1 = 0
arg2 = 0
arg3 = 32767
(gdb) p &arg1
0x7ffff3a4697ec
(gdb) p &arg2
0x7ffff3a4697e8
(gdb) p &arg3
0x7ffff3a4697e4
(gdb) info locals
local1 = 0
local2 = 0
local3 = 0
(gdb) p &local1
0x7ffff3a4697fc
(gdb) p &local2
0x7ffff3a4697f8
(gdb) p &local3
0x7ffff3a4697f4
(gdb) info frame
Stack level 0, frame at 0x7ffff3a469810:
...
Arglist at 0x7ffff3a469800, args: arg1=0, arg2=0, arg3=32767
Locals at 0x7ffff3a469800, Previous frame's sp is 0x7ffff3a469810
Saved registers:
rbp at 0x7ffff3a469800, rip at 0x7ffff3a469808
为什么函数的参数位于比局部变量和返回指针低的内存地址?所有关于该主题的文献(例如像https://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Call_stack_layout.svg/342px-Call_stack_layout.svg.png 这样的图表)都暗示参数应该位于比返回地址更高的内存地址?返回地址应该在本地和参数之间,而我在一个连续的块中有本地和参数,最后是返回地址。非常感谢 - 如果我完全误解了,我们深表歉意!
编辑:生成此代码的示例 C 程序:
#include <stdio.h>
void func1(int arg1, int arg2, int arg3) {
int local1;
int local2;
int local3;
local1 = 2;
local2 = 3;
local3 = 4;
}
int main(){
int a;
int b;
int c;
func1(a, b, c);
}
在 CentOS x86_64 上使用 gcc code.c -o code 编译此代码。使用 gdb 运行并在 func1 中放置一个断点。查看 arg 变量的地址、局部变量和返回地址。
【问题讨论】:
-
您链接到的图片没有说明任何地址的值。
-
栈顶通常表示低内存地址;如果你想要i.stack.imgur.com/Z5cSh.jpg,这里有另一张图片明确说明了这一点
-
Spectre... ;)
-
这只是一个在 Centos x86 上用 gcc(无参数)编译的简单 c 程序
-
@InnocentBystander 用 C 源代码更新了帖子
标签: c assembly x86-64 callstack stack-memory