栈(Stack)、栈溢出问题

栈(Stack)、栈溢出问题

Linux、Windows下C语言内存布局(内存模型)中曾经说到程序的虚拟地址空间分为多个区域。栈(Stack)可以存放函数参数、局部变量、局部数组等作用范围在函数内部的数据,他的用途就是完成函数的调用。

栈内存由系统自动分配和释放:发生函数调用时就为函数运行时用到的数据分配内存,函数调用结束后就将之前分配的内存全部销毁。所以局部变量、参数只在当前函数中有效,不能传递到函数外部。

栈的概念

在计算机中,栈可以理解为一个特殊的容器,用户可以将数据依次放入栈中,然后再将数据按照相反的顺序从栈中取出。也就是说,先放入的数据最后才能取出,而最后放入的数据须先取出。这被称为先进后出(First In Last Out)原则。

放入数据常称为入栈或压栈(Push),取出数据常称为出栈或弹出(Pop)。如下图:

在这里插入图片描述

可以发现,栈底始终不动,出栈入栈只是在移动堆栈,当栈中没有数据时,栈顶和栈底重合。

从本质上来讲,栈是一段连续的内存,需要同时记录栈底和栈顶,才能对当前的栈进行定位。在现代计算机中,通常使用ebp寄存器指向栈底,而使用esp寄存器指向栈顶。随着数据的进栈出栈,esp的值会不断变化,进栈时esp的值减小,出栈时esp的值增大。

ebp和esp都是CPU中的寄存器;ebp是Extend Base Pointer的缩写,通常用来指向栈底;esp是Extend Stack Pointer的缩写,通常用来指向栈顶

如下是一个栈的实例:

在这里插入图片描述

栈的大小以及栈溢出

对每个程序来说,栈能使用的内存都是有限的,一般是1M~8M,这在编译时就已经决定了,程序运行期间不能再改变。如果程序使用的栈内存超出最大值,就会发生font color=#1E90FF>栈溢出(Stack Overflow)错误。

一个程序可以包含多个线程,每个线程都有自己的栈。严格来说,栈的最大值是针对线程来说的,而不是针对程序。

栈内存的大小和编译器有关,编译器会为栈内存指定一个最大值,在VC/VS下,默认是1M,在C-Free下,默认是2M,在Linux GCC下,默认是8M。

当然,我们也可以通过参数来修改栈内存的大小。以VS2010为例,在工程名处右击,会弹出一个菜单,选择“属性”,会出现一个对话框,如下图所示:

在这里插入图片描述

该图中,我们将栈内存设置为4M。提示:栈也经常被称为堆栈,而堆依然被称为堆,所以堆栈这个概念并不包含堆,注意区分。

当程序使用的栈内存大于默认值(或修改后的值)时,就会发生栈溢出(Stack Overflow)错误。使用VS2010并切换到Debug模式,并运行以下代码:

int main(){
    char str[1024*1024*2] = {0};
    return 0;
}

局部字符数组str存储在栈上,占用2M的内存,超出了默认值1M,所以会发生栈溢出错误,如图:

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JayerZhou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值