为什么堆栈向下生长?


31

我假设有历史,但是堆栈为什么向下增长?

在我看来,像缓冲区溢出将是一个很大很难利用如果堆栈向上增长...


3
stackoverflow.com/questions/1677415/…请注意,堆栈可以某种方式增长。
JB金

6
就像这样一个问题:stackoverflow.com/questions/2035568/…。实事求是地的物质存在于这个在这里一个更好的问题和答案:stackoverflow.com/questions/664744/...
卡尔森

链接的问题不能完全解决缓冲区溢出问题。
deadalnix 2012年

1
因为堆向上生长。
tylerl 2012年

2
内存位置0在顶部还是底部?

Answers:


21

认为它来自计算的早期,那时内存非常有限,因此预先分配大量内存供堆栈专用是不明智的。因此,通过从地址零开始向上分配堆内存,并从内存末尾向下分配堆栈内存,可以使堆和堆栈共享相同的内存区域。

如果您需要更多的堆,则可以谨慎使用堆栈。如果需要更多堆栈,可以尝试释放一些堆内存。结果当然是导致崩溃的主要原因,因为堆栈偶尔会覆盖堆,反之亦然。

那时,还没有interwebz,因此就没有缓冲区溢出漏洞利用的问题。(或者至少在存在interwebz的程度上,它们全都在美国国防部的高安全性设施之内,因此无需考虑恶意数据的可能性。)

此后,对于大多数体系结构来说,都是保持与同一体系结构以前版本的兼容性。这就是为什么今天我们仍然需要颠倒的堆栈。


8
追溯到过去,没有堆,即使到今天,许多8位和16位微控制器也没有堆。堆栈变小,因此可以将程序安装在低内存地址中,而堆栈就是剩余的内存。堆栈初始化可以在程序加载之前执行,从而简化了程序。
mattnz

1
大多数小型微控制器都有一个堆,只是没有增长的堆。当您需要使用少量RAM(<1Kbytes)时,很难证明在堆上使用动态内存分配是合理的。通常,唯一更改的内存部分的大小是堆栈。
tehnyit'3

7

程序存储器通常设置为

code
constants
heap (growing up)
...
stack (growing down)

堆和栈可以交换

但是如果堆栈以其他方式进入,缓冲区溢出仍然可以被利用

以经典strcpy为例

foo(char* in){
char[100] buff;
strcpy(buff,in);
}

与堆栈内存为

ret foo
arg in
buff array
ret strcpy
buf pointer
in

这意味着复制完成后,的返回地址strcpy位于缓冲区之后(而不是foo的返回地址),并且可以被其中的任何内容覆盖in


4

某些硬件的堆从高内存开始增长,然后逐渐减少,而栈从低内存开始增长。

惠普的PA-RISC硬件以及其他功能可以做到这一点:http : //www.embeddedrelated.com/usenet/embedded/show/68749-1.php

久负盛名的Multics操作系统在具有(可能是其中之一)堆栈增长的硬件上运行:请参阅http://www.acsac.org/2002/papers/classic-multics.pdf,第2.3.2节结尾:

第三,Multics处理器上的堆栈朝着正方向而非负方向增长。这意味着,如果您实际上完成了缓冲区溢出,则将覆盖未使用的堆栈帧,而不是您自己的返回指针,从而使利用变得更加困难。

这是一个非常有趣的声明。缓冲区溢出是否仅由于“常规”过程-调用-堆栈-框架安排而成为如此巨大的问题?另外,Multics的“完全无敌”声誉仅仅是硬件设计的fl幸?


好吧,没有可执行堆栈可能对Multics起到了与智能堆栈方向一样大的作用,当然,对于用PL / 1编写的许多程序来说,字符串溢出也不是真正的问题。
格雷格·伍兹
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.