问题描述
看下面的代码:
void f()
{
f();
}
我知道因为调用了许多f()
函数,所以发生StackOverflow。
但是我的问题是,究竟是什么存储在导致此错误的堆栈中,每个f()
函数调用的返回地址?
因为此函数没有变量,所以为什么会发生StackOverflow?
解决方法
对于每个调用的函数,堆栈都存储其返回地址,以便在函数返回时在下一条指令处恢复执行。这是call stack。
,正如其他答案已经说过的,这是由于返回地址所致。
void f(){
f();
}
编译为
f:
call f #Let's assume f has the address 0x1000 for later purposes
ret
但是call
的作用是什么?
它有两件事:
- 将当前地址推入堆栈
- 呼叫指定的地址。 本质上是:
f:
push %rip
jmp 0x1000
ret
如果“展开”此呼叫,您将具有:
f:
push %rip
push %rip
push %rip
push %rip
push %rip
push %rip
....
以此类推。如您所见,您总是将地址压入堆栈。这将起作用,直到您击中其他区域并覆盖它们。 (此图假设架构具有向后增长的堆栈,例如x86)
[heap].......[stack pointer][stack] #Start
[heap]......[stack pointer][stack ] push %rip
[heap].....[stack pointer][stack ] push %rip
[heap]....[stack pointer][stack ] push %rip
[heap]...[stack pointer][stack ] push %rip
[heap]..[stack pointer][stack ] push %rip
[heap].[stack pointer][stack ] push %rip
[heap][stack pointer][stack ] push %rip
[heap[stack pointer][stack ]# Boom,you for example reached the heap and you are overwriting it.