免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
1234下一页
最近访问板块 发新帖
查看: 7412 | 回复: 32
打印 上一主题 下一主题

[C] [面试]如果交换堆和栈的位置? [复制链接]

论坛徽章:
2
嗜杀者
日期:2015-11-25 10:44:3015-16赛季CBA联赛之北京
日期:2016-03-20 19:50:17
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-04-22 21:04 |只看该作者 |倒序浏览
本帖最后由 hitcser01 于 2014-05-05 22:20 编辑

进程在内存中的分布大概是: 代码段-数据段-bss段-堆-栈-环境变量

为什么不是 代码段-数据段-bss段-栈-堆-环境变量

为什么我们是按照前者来实现而不是后者呢? 前者相对后者有何优势?

我认为如果按照后者来实现,可以让栈和堆都向中间增长,程序在被载入内存的时候确定栈和堆的位置这并不难,和第一种方法一样.
1.从技术角度讲, 让栈和堆都向中间增长在实现/使用时有何困难呢? 我没想到.
2.从面试角度讲, 当时我没有明确表达出"栈和堆都向中间增长"的意思,默认了这种情况.难道面试官仍然默认栈向下增长会和其它内容冲突的情况?

CU的各位朋友在哪里? 来来来,帮忙解释解释,谢谢!

论坛徽章:
3
15-16赛季CBA联赛之山东
日期:2016-10-30 08:47:3015-16赛季CBA联赛之佛山
日期:2016-12-17 00:06:31CU十四周年纪念徽章
日期:2017-12-03 01:04:02
2 [报告]
发表于 2014-04-23 01:13 |只看该作者
按照通常的设计, 栈向下增长, 堆向上增长.
比如按照用户空间 3G 来看, 栈在 3G 下一个随机地址开始, 堆在 bss 上一个随机地址开始. 这样空间的利用相对完全(想象一下它们能碰头的情况).

如果将栈设计在 bss 之上, 堆设计在栈之上.
那么这时的问题在于,
1. 栈空间大小固定多少合适? 如果栈向下增长的话栈顶可能会碰到 bss 段的.
2. 如果把栈设计为向上增长, 那堆的起始点设计在哪里合适? 其实是同一个问题: 栈空间要固定吗, 如果固定, 固定为多少?

所以传统的通常设计, 反正堆起始点之上, 栈起始点之下就是堆和栈的空间. 如果栈顶碰到堆顶, 那就说明空间不够用了. 这种设计相对灵活.

其实这仍然是比较扯淡的问题. 实际上 Linux 32 位系统通常将用户的栈空间限制为 10 MB. 不过可以解除这个限制.
另外, 栈和堆之间还有 mmap 区域, 用来 map 各种共享库. 所以一般栈顶堆顶碰头的情况是... sigh...

不想扯淡面试官有没有人品问题. 不过 LZ 面试失败, 一句话, 就是面试官看你不爽, 不爽, 不爽. 这种不爽, 可能是因为 LZ 的技术问题, 也可能是因为 LZ 的人品问题, 还可能是因为 LZ 的相貌问题. 不过根据 LZ 这个题目来看, 技术问题原因导致失败的可能性比较大一些.

论坛徽章:
2
嗜杀者
日期:2015-11-25 10:44:3015-16赛季CBA联赛之北京
日期:2016-03-20 19:50:17
3 [报告]
发表于 2014-04-23 06:37 |只看该作者
@captivated
先探讨一下技术,
我认为如果按照后者来实现,可以让栈和堆都向中间增长,程序在被载入内存的时候确定栈和堆的位置这并不难.
我突然想起来了, 我默认后者就是可以让栈和堆都向中间增长,难道面试官想考察如果栈向下增长的话栈顶可能会碰到 bss 段的情况......

面试官最后说的是非要这样做也行,只是肯定不如原来的好.

他看我不爽应该是我技术问题 X~X

论坛徽章:
3
15-16赛季CBA联赛之山东
日期:2016-10-30 08:47:3015-16赛季CBA联赛之佛山
日期:2016-12-17 00:06:31CU十四周年纪念徽章
日期:2017-12-03 01:04:02
4 [报告]
发表于 2014-04-23 11:20 |只看该作者
回复 3# hitcser01


    确实堆向下增长的话也不是不可以, 我也考虑过了. 不过一般对堆上访问地址是递增的, 可能仅从保持一致性的角度来说... 堆顶设计为向上增长比较好.

    我也觉得这是个扯淡问题. 反正目前的 Linux 系统实现是向上调整堆顶. 说白了这是个历史选择问题, 反正原来技术就是这么实现了, 非要换个实现方式也不是不可以... 比如说 C 语言数组语法一致性不够好有缺陷什么的, 也不是不可以换掉 C 啊, 那行把各种操作系统什么的推倒重来实现一遍就可以啦, 可是 C 这个抽象级别的语言就用 C 也好好的啊, 那干嘛要搞这搞那...

    至于面试官是不是真有人品问题, 这个难得扯清楚, 所以就不扯了. 祝 LZ 下次好运.

论坛徽章:
26
处女座
日期:2016-04-18 14:00:4515-16赛季CBA联赛之深圳
日期:2020-06-02 10:10:5015-16赛季CBA联赛之广夏
日期:2019-07-23 16:59:452016科比退役纪念章
日期:2019-06-26 16:59:1315-16赛季CBA联赛之天津
日期:2019-05-28 14:25:1915-16赛季CBA联赛之青岛
日期:2019-05-16 10:14:082016科比退役纪念章
日期:2019-01-11 14:44:062016科比退役纪念章
日期:2018-07-18 16:17:4015-16赛季CBA联赛之上海
日期:2017-08-22 18:18:5515-16赛季CBA联赛之江苏
日期:2017-08-04 17:00:4715-16赛季CBA联赛之佛山
日期:2017-02-20 18:21:1315-16赛季CBA联赛之天津
日期:2016-12-12 10:44:23
5 [报告]
发表于 2014-04-23 12:08 |只看该作者
好高端的样子啊

论坛徽章:
2
嗜杀者
日期:2015-11-25 10:44:3015-16赛季CBA联赛之北京
日期:2016-03-20 19:50:17
6 [报告]
发表于 2014-04-23 13:00 |只看该作者
回复 4# captivated
谢谢, 看来我还是得加强自己.

   

论坛徽章:
2
嗜杀者
日期:2015-11-25 10:44:3015-16赛季CBA联赛之北京
日期:2016-03-20 19:50:17
7 [报告]
发表于 2014-04-23 13:01 |只看该作者
回复 5# evaspring
大神不要卖萌, 快来一起讨论喽!


   

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
8 [报告]
发表于 2014-04-23 13:14 |只看该作者
我说几点我自己的理解吧。对于堆和栈来说,最重要的事情在于:堆和栈的适用环境是不一样的。

有什么区别呢?栈倾向于短暂、少量、可按序分配的情形,而堆适合长期、大量、随机分配、释放的场景。我们想想堆和栈目前的实现方法:栈在栈顶之外,有一些保护的内存页,一旦访问,则产生中断,产生新的页面,并且将保护内存页提前。换句话说,就是按照使用来分配。而堆是随用随分配,直到空间不足直接由库函数进行brk来完成。

上面提到的不同的实现方法,是导致堆栈如此设计的原因吗?我觉得不是的……真实的原因嘛……







我觉得是因为X86在设计之初push和pop命令的加减就决定了堆栈的方向问题233333333333


回过头来说,我说说堆栈这么设计的好处:首先,程序跑飞的时候,最容易出问题的是栈空间——任何CALL机器码都会导致栈增长。想象一下如果栈朝上涨会怎么样。跑飞以后栈会侵入高地址区域的IO映射区,操纵硬件,造成严重后果(IBM某显示器就可以直接被这样烧掉)。如果栈是向下增长的。那么push到最后也就是地址归零然后跑到当前段的最末尾继续往前写,不会殃及池鱼到高地址的IO区。

不过话说回来对X86的DOS来说殃及到低地址的中断向量区也是很要命的事情地说……

反正这事儿得问Intel为嘛机器指令要这么设计了。如果我印象没错是有栈向上增长的计算机的。

论坛徽章:
2
嗜杀者
日期:2015-11-25 10:44:3015-16赛季CBA联赛之北京
日期:2016-03-20 19:50:17
9 [报告]
发表于 2014-04-23 14:42 |只看该作者
本帖最后由 hitcser01 于 2014-04-23 14:57 编辑

回复 8# starwing83

:wink:

有点疑问,
I/O映射区 好像不在程序的地址空间里(?), 栈向上涨最多覆盖环境变量那块然后就到了整个地址空间的末尾?
我知道的是 0x000 0000 ~ 0xC00 0000 属于用户程序;  最高的1G系统保留,I/O 应该映射到这里? 各种分段/分页能够保证不会push侵入到最高的1G空间.
这样的想法是哪里有问题吗...

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
10 [报告]
发表于 2014-04-23 15:22 |只看该作者
本帖最后由 windoze 于 2014-04-23 15:25 编辑

这不是个问题。
heap只是个概念,随便找一块内存(除了一些特定的保留区域)都可以拿出来做heap,哪怕是不连续的几块都没问题,所有“增强型”的malloc其实都是这么做的,比如tcmalloc、ptmalloc、libumem之类。
至于stack无非就是stack base和stack pointer,随便在可用内存里找一块都可以拿来做stack,创建很也多个没问题,放在heap里也没问题,C标准里的setjump/longjump干的就是这个,所有第三方coroutine库如ucontext或者Windows下的Fiber干的事也差不多,从宽泛一点的角度讲thread干的事也差不多,唯一的限制恐怕就是pop/push时特定的CPU移动栈指针的方向是固定的。

PS.忽然想起来GCC/Clang现在支持segmented stack,也就是说stack和heap现在可以交织成梳状{:2_176:} …………
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP