函数的局部变量是如何从堆栈中访问的
How are the function local variables accessed from the stack?
来源http://www.learncpp.com/cpp-tutorial/79-the-stack-and-the-heap/
以下是当函数调用:
- 函数调用之外的指令的地址被推送到堆栈上。这就是CPU在函数返回
- 堆栈上为函数的返回类型留出了空间。这只是一个占位符
- CPU跳转到函数的代码
- 堆栈的当前顶部保存在一个称为堆栈帧的特殊指针中
- 在这一点之后添加到堆栈中的所有内容都被认为是函数的"本地"
- 所有函数参数都放置在堆栈上
- 函数内部的指令开始执行
- 局部变量在定义时被推送到堆栈中
我不确定第6点是如何运作的。如果所有函数参数都放在堆栈上,如何访问它们?
例如,如果有三个参数a
、b
和c
,并且从的顶部像这样放置在堆栈上
| a |
| b |
| c |
| |
...
|___|
现在,当函数想要访问c
时会发生什么?是否弹出a
和b
?
堆栈是隐喻堆栈。请记住它仍然是一个RAM,因此如果您知道要查找什么,您可以访问每个地址,而无需弹出其余地址。
由于自动变量的大小在编译时是已知的-编译器为每个变量标记offset
,因此偏移量是从堆栈开始的自动变量部分[或堆栈的头,两者都是有效的,具体实现可能取决于体系结构]确定的,并且它只通过:start + offset
为每个变量的偏移量访问它们。
esp
注册表)指向a
,esp+8h
指向b
,esp+16h
指向c
等等。不需要弹出a
。
请注意,这是一个实现细节。你不应该担心这些。我给出的数字纯粹是理论上的,在一些架构中,递减地址被赋予后一个参数,而在另一些架构中则相反。无法保证会发生这种情况。
编辑:在我看来,这不是一个非常可靠的信息来源。它谈到了堆栈和堆,但这些都是实现细节,甚至可能不存在。
标准中也没有任何约束,任何东西都可以通过堆栈来实现。例如,我生成了以下代码:
void foo(int x, int y, int z)
{
01241380 push ebp
01241381 mov ebp,esp
01241383 sub esp,0CCh
01241389 push ebx
0124138A push esi
0124138B push edi
0124138C lea edi,[ebp-0CCh]
01241392 mov ecx,33h
01241397 mov eax,0CCCCCCCCh
0124139C rep stos dword ptr es:[edi]
int c = x;
0124139E mov eax,dword ptr [x]
012413A1 mov dword ptr [c],eax
c = y;
012413A4 mov eax,dword ptr [y]
012413A7 mov dword ptr [c],eax
c = z;
012413AA mov eax,dword ptr [z]
012413AD mov dword ptr [c],eax
}
012413B0 pop edi
012413B1 pop esi
012413B2 pop ebx
012413B3 mov esp,ebp
012413B5 pop ebp
所以你看,那里没有堆栈。运行时可以直接访问元素:dword ptr [x]
等。
它使用堆栈指针和相对地址来指出c.
相关文章:
- 用于解析 win64 堆栈跟踪的命令行客户端(可以访问符号服务器)
- 堆栈上的 C++ 访问冲突写入异常
- 嵌套容器:为什么我无法访问堆栈队列顶部的堆栈?C++
- 是否可以访问代码中的调用堆栈?
- 在C++中使用链表的堆栈实现中,访问结构体headNode成员count和top会导致运行时错误
- 访问旧的堆栈帧
- 复制堆栈上的成员值或使用指针访问它?
- x64 DLL 堆栈访问超出范围?
- 访问其他线程堆栈变量如何在C++中工作?
- 启用 MSVC 调试迭代器时堆栈分配器访问冲突
- 调用堆栈中的访问冲突
- STL堆栈:读取访问冲突
- 我需要一个像堆栈一样的数据结构,但具有随机访问,但是,我应该实现什么
- 堆栈引发内存访问冲突
- 哪个访问堆栈或堆更快
- 无法寻址的访问超出堆栈顶部
- 访问堆栈变量的速度比取消引用指针慢
- 异常对象在哪里有其空间、堆或堆栈,以及如何在不同的类中访问它
- 如何访问调用堆栈
- 访问堆栈和队列时发生运行时错误