【发布时间】:2012-03-22 23:59:00
【问题描述】:
我正在学习汇编课程,我们目前正在学习堆栈。从我了解到的所有东西都必须最终弹出(清理堆栈)。为什么我们绝对需要清理堆栈?我读过它是为了防止内存泄漏,是吗?
非常感谢
【问题讨论】:
我正在学习汇编课程,我们目前正在学习堆栈。从我了解到的所有东西都必须最终弹出(清理堆栈)。为什么我们绝对需要清理堆栈?我读过它是为了防止内存泄漏,是吗?
非常感谢
【问题讨论】:
对于给定的执行线程,只有一定数量的堆栈。
它的目的是临时保存调用函数时需要的数据(如返回地址和传递给函数的参数)。
如果你在函数退出时不清理堆栈,你最终会耗尽堆栈空间。
此外,作为一般规则,不只是堆栈,您的程序使用的任何资源(堆栈空间、堆空间、文件句柄等)都应保留尽可能短的时间,以提高整体效率。
【讨论】:
堆栈是有限数量的内存,与任何内存分配系统一样,如果您从不清理它,它只会不断增长。最终你会溢出堆栈,当你覆盖其他内存区域或只是生成一个无效地址时,所有的地狱都会崩溃。
【讨论】:
如果不清理堆栈,调用函数将如何找到它的变量?被调用者将运行,对堆栈上的自己的变量进行一些操作,然后返回给调用者 - 现在如果堆栈指针发生了变化,调用者可以做什么?它如何恢复它以找出它自己的堆栈变量在哪里?唯一的答案是清理堆栈 - 谁来做(被调用者或调用者)并不重要,但某人必须这样做。
术语“内存泄漏”通常是指丢失指向动态内存分配的指针,因此您无法free() 该分配。
【讨论】:
除了其他答案之外,我使用的大多数处理器都将函数调用的返回地址放在堆栈上。
RET/RTS(或任何用于您的处理器的返回语法)只是从堆栈中提取返回地址并将 PC、ProgramCounter 设置为该地址。
如果函数将其他变量放入堆栈但不删除它们,则 RET 将拉回错误的值并返回到错误的地址,从而导致各种奇怪的行为和/或异常/陷阱。
由这种行为引起的故障可能会变得非常难以调试,尤其是如果它们没有立即发生故障
【讨论】:
软件例程(函数)可以共享堆栈以获取调用参数并返回变量以及记住调用者的返回地址。
由于汇编中的堆栈指针通常是一个寄存器,它是一种全局变量。如果在函数结束时,堆栈指针没有设置到正确的位置(“堆栈清理”),就会发生很多不好的事情。系统会返回错误的地址,调用者会弹出错误的返回值,可能会出现堆栈溢出、下溢等情况。
【讨论】:
每个函数都可能使用堆栈,即使有些函数不使用堆栈,您也会在程序中嵌套函数调用 one() 调用 two() 两个调用 three(),等等。
因此,如果函数一在堆栈上有局部变量 A、B、C,那么它调用二,二有两个变量,它在堆栈上使用 E 和 F。然后 3 在堆栈上有 G 和 H。如果您不将堆栈指针恢复到进入三个时的位置,当您返回两个时,它会认为它正在访问 E 和 F,而是会访问 G 和 H 或其他内容,具体取决于三个的堆栈帧() 功能。
不会发生内存泄漏,而是会崩溃。有时你很幸运并且幸存下来,这可能是这些函数的代码的本质,但通常它会导致你为调用你的更高级别函数编译的代码失败。
现在是内存泄漏类似,因为一个函数正在破坏其他人的内存,当然。
在处理器使用堆栈作为返回值的情况下,这只会使情况变得更糟,崩溃或奇怪的行为更有保证,而且更糟。
【讨论】: