我们知道C语言中,每个栈帧对应着一个未运行完的函数。栈帧中保存了该函数的返回地址和局部变量。栈帧也叫过程活动记录,是编译器用来实现函数调用的一种数据结构。那么在Linux下gcc编译器栈帧是怎么实现的呢?
首先来看下面这段代码:
这段代码的运行结果是会导致虚拟机重启。通过代码可以看到我们在fun函数中写了让系统重启的代码然而我们在main函数中并没有调用fun函数,却仍旧导致了系统重启。
首先要我们知道栈是从高地址向低地址生长的,每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址)。由此我们来用图的方式说明这个问题。
fun1中p是形参a的地址,p--之后p则成了fun1运行后的下一条指令的地址,但是fun1中将*p=fun这句代码使得下一条指令的地址变成了fun的地址因此在main函数没有调用fun的的情况下执行了fun函数。
再来看下这个代码:
容易知道a先压栈,b后压栈。 压栈时,栈顶由高地址向低地址方向前进,因此,结果为:
变量a的地址 0xbfa92d88
变量b的地址 0xbfa92d84
时间: 2024-10-20 08:50:08