从堆栈结构说线程的代价

 

今天休息,并且也没有什么其它事情需要完成,所以就对程序堆栈进行了调试查看。

 

以前一直没有认真追究过程序的堆栈,只是觉得书上说的就是对的,并不需要验证,所以对程序堆栈的体会只是停留在书本上的描述。

 

实验工具:一台电脑,VS2008软件(其它工具也可以了,只是我机子装的是这个IDE

 

实验目的:我想知道程序堆栈在内存中如何组织,启动一个线程占用了什么资源?最多可以启动多少个线程?

 

实验过程:

我随便写了个程序,在主函数入口处打了断点,当调试停下时,转到汇编代码查看,此时我们观察Esp的值,会发现这个值大约是一个1开始的16进制的6位数,这就说明一个程序堆栈的起始地址就是1xxxxx这个地方了。

从函数入口处的几句汇编代码可以看出,程序在入口栈的基础上空出了一片空间,代码例如:sub         esp,100h ,后边空出多大空间这个数字是变化的,要知道它是干什么用的之前,最好先知道它的大小变化时什么引发的,你如果测试几个程序就可以发现,它随着函数中变量的增加而变大,所以这可以充分说明这块空出来的空间就是为函数内变量存放数据准备的。

 

 

子函数的堆栈是怎么回事?

 

我们在调用一个子函数时,会将需要的参数压入堆栈,这个时候子函数就在堆栈当前位置进行与父函数一样的操作,即空一片空间,给自己函数内的变量使用,函数返回后调用者出栈参数信息。

 

 

这样,我们就有了下一个问题,子函数可以一直递归调用下去吗?内存用尽才是尽头吗?还是程序堆栈是有限定大小的?

 

我们随便写一个函数无限递归调用的测试程序,递归函数内声明一个1000的整型数组,这样堆栈生长能够更快,当然数组越大生长越快。

程序很快就爆了,当然这和我们预期也是相同的,这个时候我们去查看堆栈位置时,发现,堆栈位置大约在0x3XXXXX的位置,这说明了什么呢?说明程序的堆栈不是无限的,也说明了再往后的空间要用作其它用途了,也就是要作为程序堆空间使用。

 

 

现在,我们知道了程序堆栈空间的位置,也知道了栈空间的大小,那么堆空间是剩下的所有空间吗?

 

我通过编写一次分配很大很大的空间,基本上说明了堆就是剩余的空间。

 

 

那么堆空间里都有什么?除了存放全局数据,动态分配数据,还有其它用途吗?在思考这个问题前,也许我们该问问自己,程序中启动多线程,线程空间在哪里?

 

我们可以先理性的思考下,如果线程空间类似于函数调用方式是否可以,很明显不可以,因为一个程序多个线程是并行执行的,所以按函数调用方式来进行线程空间分配必然造成函数调用时堆栈混乱的局面,那么既然不能按函数调用方式分配空间,那么就只能在堆栈空间中分配了,所以我们的线程启动函数一般都有一个线程堆栈空间大小设定的参数,当线程中函数也出现了上边类似函数递归调用堆栈空间用尽的问题时,程序自然也会爆了,我们也就中奖了,呵呵。

通过这样的分析,我们自然而然就知道,一个程序不可能启动无限多的线程,我测试的结果是,一个程序一般可以启动2000个左右的线程。

从上边的分析,因为动态分配的内存,与启动的线程共用所有堆空间,所以,线程的多少取决于两个因素,一是每个线程堆栈大小,另一个是所有线程请求的动态内存大小,当然,反过来说,动态内存申请成功与否也是与线程的多少有很多关系的,当一个程序开了2000多个线程的时候,这个时候申请内存一般都会失败。这个我也是经过测试确认了的。

 

 

通过这次对堆栈测试,让我感觉充分任务了程序的线程之间的关系。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值