全面介绍Windows内存管理机制及C++内存分配实例(六):堆栈

本文背景:

在编程中,很多WindowsC++的内存函数不知道有什么区别,更别谈有效使用;根本的原因是,没有清楚的理解操作系统的内存管理机制,本文企图通过简单的总结描述,结合实例来阐明这个机制。

本文目的:

Windows内存管理机制了解清楚,有效的利用C++内存函数管理和使用内存。

本文内容:

本文一共有六节,由于篇幅较多,故按节发表。其他章节请看本人博客的Windows内存管理及C++内存分配实例(一)(二)(三)(四)和(五)。

 

 

6.      内存管理机制--堆栈 (Stack)

·        使用场合

操作系统为每个线程都建立一个默认堆栈,大小为1M。这个堆栈是供函数调用时使用,线程内函数里的各种静态变量都是从这个默认堆栈里分配的。

·        堆栈结构

默认1M的线程堆栈空间的结构举例如下,其中,基地址为0x0004 0000,刚开始时,CPU的堆栈指针寄存器保存的是栈顶的第一个页面地址0x0013 F000。第二页面为保护页面。这两页是已经分配物理存储器的可用页面。

随着函数的调用,系统将需要更多的页面,假设需要另外5页,则给这5页提交内存,删除原来页面的保护页面属性,最后一页赋予保护页面属性。

当分配倒数第二页0x0004 1000时,系统不再将保护属性赋予它,相反,它会产生堆栈溢出异常STATUS_STACK_OVERFLOW,如果程序没有处理它,则线程将退出。最后一页始终处于保留状态,也就是说可用堆栈数是没有1M的,之所以不用,是防止线程破坏栈底下面的内存(通过违规访问异常达到目的)。

 

 

当程序的函数里分配了临时变量时,编译器把堆栈指针递减相应的页数目,堆栈指针始终都是一个页面的整数倍。所以,当编译器发现堆栈指针位于保护页面之下时,会插入堆栈检查函数,改变堆栈指针及保护页面。这样,当程序运行时,就会分配物理内存,而不会出现访问违规。

·        使用例子

改变堆栈默认大小:

有两个方法,一是在CreateThread()时传一个参数进去改变;

二是通过链接命令:

#pragma comment(linker,"/STACK:102400000,1024000")

第一个值是堆栈的保留空间,第二个值是堆栈开始时提交的物理内存大小。本文将堆栈改变为100M

         堆栈溢出处理:

        如果出现堆栈异常不处理,则导致线程终止;如果你只做了一般处理,内

        结构已经处于破坏状态,因为已经没有保护页面,系统没有办法再抛出堆栈溢

        出异常,这样的话,当再次出现溢出时,会出现访问违规操作

        STATUS_ACCESS_VIOLATION,这是线程将被系统终止。解决办法是,恢复

  • 0
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 16
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值