空函数的stackoverflow

问题描述

看下面的代码

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的作用是什么? 它有两件事:

  1. 将当前地址推入堆栈
  2. 呼叫指定的地址。 本质上是:
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.