为什么栈空间的访问速度要快于堆

haofang666777 2012-09-20 09:09:57
如题,向各位高手请教(今天面试被问到了,悲剧)
...全文
4711 71 打赏 收藏 转发到动态 举报
写回复
用AI写文章
71 条回复
切换为时间正序
请发表友善的回复…
发表回复
rfd520hly 2012-10-07
  • 打赏
  • 举报
回复
很明显,栈的读取速度比堆要有快,请追问!请指教!
rfd520hly 2012-10-07
  • 打赏
  • 举报
回复

堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。
堆中存储引用变量所引用的对象,通常new出来的都是
灵活性强,叠起来的砖块一样,可以任意写,读,删,插,先进先出
堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。
但缺点是,由于要在运行时动态分配内存,存取速度较慢。



栈区(stack)— 由编译器自动分配释放 ,栈内存储程序中定义的变量(基本类型和引用类型)
像子弹夹一样,必须一个一个读,先进后出
栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。另外,栈数据可以共享,

但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。
sunny 2012-10-07
  • 打赏
  • 举报
回复
[Quote=引用 68 楼 的回复:]

引用 66 楼 的回复:
这个差距可以忽略吧?就是指令的问题,在栈中,一般通过EBP直接加上偏移来访问数据;如果数据在堆中,一般是获取到一个指针,将该指针放在寄存器中,然后加上偏移来访问,多1-2个指令周期吧。至于二者数据在内存中地位是一样的,所以访问速度应该没有区别。


保护模式下当然看不出区别,大多数跟堆里申请的内存都不是连续的,是线性连续,物理不连续。
[/Quote]

即使在ring0级别(只要是实模式转换之后),地址映射是针对所有地址的,是不分堆和栈的,所以,物理内存的不连续,同样会存在于栈中。
可见一斑 2012-10-07
  • 打赏
  • 举报
回复
[Quote=引用 66 楼 的回复:]
这个差距可以忽略吧?就是指令的问题,在栈中,一般通过EBP直接加上偏移来访问数据;如果数据在堆中,一般是获取到一个指针,将该指针放在寄存器中,然后加上偏移来访问,多1-2个指令周期吧。至于二者数据在内存中地位是一样的,所以访问速度应该没有区别。
[/Quote]

保护模式下当然看不出区别,大多数跟堆里申请的内存都不是连续的,是线性连续,物理不连续。
sunny 2012-10-06
  • 打赏
  • 举报
回复
[Quote=引用 65 楼 的回复:]

Stack由CPU提供指令直接控制, 而heap由OS管理分配。怎么可能没有差距。 而且OS喜欢玩延迟申请, 所以给人错觉是无差距。 你写写数据试试。
[/Quote]

诧异,一般heap的申请都是一次申请大块,然后再交给用户,所以不存在延迟申请的问题。写数据的问题不是读写内存的问题,是使用API的问题(系统为了效率,采用延时写入方式),如果仅仅是往一个内存块中写大量数据,heap与stack我认为没有什么差别。
sunny 2012-10-06
  • 打赏
  • 举报
回复
这个差距可以忽略吧?就是指令的问题,在栈中,一般通过EBP直接加上偏移来访问数据;如果数据在堆中,一般是获取到一个指针,将该指针放在寄存器中,然后加上偏移来访问,多1-2个指令周期吧。至于二者数据在内存中地位是一样的,所以访问速度应该没有区别。
piaoer23 2012-10-05
  • 打赏
  • 举报
回复
Stack由CPU提供指令直接控制, 而heap由OS管理分配。怎么可能没有差距。 而且OS喜欢玩延迟申请, 所以给人错觉是无差距。 你写写数据试试。
cao_julians 2012-10-03
  • 打赏
  • 举报
回复
[Quote=引用 62 楼 的回复:]
栈是局部的,程序开支就知道位置,所以创建一个变量只要push一下,
但是堆不一样,堆要向系统请求,寻找合适的块,检查错误,返回地址,当然慢
[/Quote]
并不是叫“栈”,就使用push操作----可以看看汇编码,对局部变量的访问不是用“push"
崔小涣 2012-10-03
  • 打赏
  • 举报
回复
学习了,全是大神。
miliggate 2012-10-01
  • 打赏
  • 举报
回复
栈是局部的,程序开支就知道位置,所以创建一个变量只要push一下,
但是堆不一样,堆要向系统请求,寻找合适的块,检查错误,返回地址,当然慢
wolf_you 2012-09-28
  • 打赏
  • 举报
回复
哎,你直接说直接取址和间接取址的差距了...[Quote=引用 8 楼 的回复:]

栈中的内存通过SP寄存器定位,堆中的内存通过某个寄存器定位到一个包含一个地址的内存,然后再通过这个地址定位到具体的内存位置。堆多了一级间接,所以综合来说会比栈慢。
另外由于栈访问比较频繁,被高速Cache缓存的几率比较大,速度也会快一点。
[/Quote]
Y2D4M4X8 2012-09-27
  • 打赏
  • 举报
回复
堆栈操作,汇编里直接有这个指令,可以通过修改栈顶指针访问或者压入数据,所以速度快。
而堆,很多时候,就是一个标明存储空间的链表,你要从链表头部开始线性搜索,当然慢了
富莱工作室 2012-09-27
  • 打赏
  • 举报
回复
当前栈指针加上要分配的大小, 就完成了桟分配, 超级快, 无需考虑多线程之类的情况

堆分配, 首先要上锁, 因为可能有多线程使用HEAP, 而后要查找可用的内存块, 标记,
反复进行不同大小的堆分配、堆释放, 还可能出现大量内存碎片

堆分配远比桟分配复杂, 栈分配更快是有道理的,

另外的.net 的堆分配应该c++的堆分配快的多, 接近桟分配速度
williamhong 2012-09-26
  • 打赏
  • 举报
回复
大部分情况,栈是程序一开始就分配好的一块内存,是固定的,堆内存是程序运行后问操作系统申请的,访问栈的内存必须要间接寻址,栈地址大多数情况下存在专用的寄存器中,如果直接访问堆内存不间接间寻址的话,访问堆比访问栈还要快,大部分堆内存操作需要间接寻址,而存堆内存地址的地方本来也是一块内存,当然没有专用的寄存器快,这种情况访问栈比访问堆要快。大致是这样,现在的操作系统很多,内存管理也很不一样,不能一概而论。
zhuyie 2012-09-25
  • 打赏
  • 举报
回复
1. 题目问的是“访问速度”,因此一堆人论证堆的分配如何慢,都和题目没有关系;
2. 用栈上的直接变量和指向堆内存的指针变量来比较访问速度,并不公平,后者必然会要费一些;应该用指向栈内存的指针和指向堆内存的指针来比较才合理。我没有实际测试,但猜测会差不太多;
有新工作否 2012-09-25
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]
栈用来存放局部变量,堆一般用来动态分配。

C/C++ code


int func(void)
{
int tmp;//使用栈空间
int *ptr=NULL;
ptr=(int *)malloc(sizeof(tmp));//使用堆
free(ptr);
ptr=NULL;
return 0
}


在使用栈时,……
[/Quote]
堆栈,我老分不清,我知道代码里怎么分配,但是中文这2个字,我老分不清。当初翻译的时候就没翻译好,一点实际意义都没有。都怪翻译的人,以后等俺牛了,重新命名这2个字!
  • 打赏
  • 举报
回复
一个是指令集的,一个是要通过系统库去实现
haofang666777 2012-09-25
  • 打赏
  • 举报
回复
。。。都是大牛 都说得有理,结贴了
pl___ 2012-09-24
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 的回复:]

C/C++ code

void func(void)
{
int tmp,*ptr=NULL,tmpmid;
ptr=(int *)malloc(sizeof(tmp));
tmp=1;
*ptr=2;
tmpmid=tmp;
tmpmid=*ptr;
free(ptr);
ptr=NULL;
}


看它的汇编代码
Ass……
[/Quote]

没开优化吧
  • 打赏
  • 举报
回复
不知道
加载更多回复(47)

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧