关于堆栈的探讨-跟初学者讲堆栈实录

关于堆栈的探讨

李问:每个进程一个堆,每个线程一个栈是什么意思?
我答:进程就像一个工厂,线程是工人.
空的工厂是不能干活的,会在最后一个工人离场的时候被系统关闭.
系统提供一个默认的堆和为每个线程工人提供一个栈.
我问:堆是什么?栈是什么?
李答:堆是下往上,栈是从上往下,堆嘛,堆起来的.

我解释:系统需要给用户代码一个生存的地方.所以预先申请了堆栈为用户代码的初始化.
堆,栈都是内存.并无本质差别.
系统并不关心R3的堆栈情况,这些是由库函数负责的。
库函数提供了两个接口:

堆申请(参数:长度)
栈申请(参数:长度)

系统会从内存中寻找足够的长度.
李答:
如果找不到会怎样?

我答:
找不到会返回错误给调用函数的人.程序员自行选择处理措施.
VC编译器默认的栈大小为1MB。
比如:
同样是:0,1,2,3,4 5个长度.
当申请的是栈stack的时候:返回5号位置
当申请的是堆heap的时候:返回0号位置

你还记得什么是递归吗?
递归每次调用都有局部变量,如果一直调用下去就会爆堆,也就是
stack overflow这是著名程序员问题求解网站的地址.

李问::有时我的电脑会卡也是这个原因了,栈溢出会导致系统崩溃吗?
**我答:**No,系统卡有1000种原因,但是栈溢出会弹出错误窗口,系统才不在乎你的程序是否栈溢出,它只会在你出问题的时候把你清理掉,并不会让系统崩溃.

我在写递归快排1000万数据的时候会出现stack-overflow.
当时通过堆虚拟机的灵感,写了一小段将栈切换到堆上的代码.欺骗程序运行在我们自己的栈上.

long m_esp;
    size_t stackLen = 1000 * 1000 * 100;
    char* p = new char[stackLen];//栈是不需要清零的
    char* pstack = p + stackLen - 1;//看,这不就是从内存的高位置开始吗
    _asm {

        mov m_esp, esp;
        mov esp, pstack;
    }
//在这里进行其他操作
_asm {
        mov esp, m_esp;
    }
    delete[]p;

然后VisualStudio的参数显示机制基本失效了….

注意,实际上程序员说的栈更多是用堆模拟的栈,系统给每个线程分配的栈它自己会在恰当的回收.
并且接口很隐蔽.记得花了一些周折才找到这个接口.得使用未公开函数.
kernel32.dll中的BaseCreateStack()
它并没有打算给程序设计者们使用它.
我渐渐开始厌恶去挖掘Windows这种未公开函数.
我认为把时间花在公开的通用的更高层次的设计上的意义更大.

/*
本文隐藏了堆的管理知识.以及内存管理的相关知识.
递归爆栈的情况:估计对方掌握并不是很清晰.
让接触者亲自申请堆,以及用图形化工具去查看堆栈分布效果会更好.
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值