zoukankan      html  css  js  c++  java
  • Stack overflow 编译能通过,运行时出现Stack overflow

    大家都知道,Windows程序的内存机制大概是这样的,全局变量(局部的静态变量本质也属于此范围)存储于堆内存,该段内存较大,一般不会溢出; 函数地址、函数参数、局部变量等信息存储于栈内存,VC6中栈内存默认大小为1M,对于当前日益扩大的程序规模而言,稍有不慎就可能出问题。
    (动态申请的内存即new出来的内存不在栈中)

    即如果函数这样写:
    void test_stack_overflow()
    {
    char* chdata = new[2*1024*1024];
    delete []chdata;
    }
    是不会出现这个错误的,而这样写则不行:
    void test_stack_overflow()
    {
    char chdata[2*1024*1024];
    }
    大多数情况下都会出现内存溢出的错误,不信在vc6中随便做个程序,调用一下这个函数试式。


    出现栈内存溢出的常见原因有2个:
    1> 函数调用层次过深,每调用一次,函数的参数、局部变量等信息就压一次栈。
    2> 局部静态变量体积太大
    第一种情况不太常见,因为很多情况下我们都用其他方法来代替递归调用(反正我是这么做的),所以只要不出现无限制的调用都应该是没有问题的,起码深度几十层我想是没问题的,这个我没试过但我想没有谁会把调用深度作那么多。检查是否是此原因的方法为,在引起溢出的那个函数处设一个断点,然后执行程序使其停在断点处, 然后按下快捷键Alt+7调出call stack窗口,在窗口中可以看到函数调用的层次关系。

    第二种情况比较常见了,我就是犯了这个错误,我在函数里定义了一个局部变量,是一个类对象,该类中有一个大数组,大概是1.5M。

    解决办法大致说来也有两种:
    1> 增加栈内存的数目
    2> 使用堆内存
    增加栈内存方法如下,在vc6种依次选择Project->Setting->Link,在Category中选择output,在Reserve中输入16进制的栈内存大小如:0x10000000,然后点ok就可以了。

    其他编译器也有类似的设置,个人认为这不是一个好办法,有一个致命原因,不知道有没有人遇到过,我把栈内存改大后,与数据库建立不了连接了(ADO方式,Acess数据库),把栈内存还原,问题立刻消失。不知道究竟是什么原因,有知道的可以告诉我。

    第二种解决办法是比较可行的,具体实现由很多种方法可以直接把数组定义改成指针,然后动态申请内存;也可以把局部变量变成全局变量,一个偷懒的办法是直接在定义前边加个static,呵呵,直接变成静态变量(实质就是全局变量)。即可以把上例中的函数这么写:

    void test_stack_overflow()
    {
    static char chdata[2*1024*1024];
    }


    当然,除非万不得已,尽量不要使用这么大的数组,出现这种情况多半说明程序结构有问题。

    ============================

    栈溢出了。栈的默认大小1M,超过就出问题了。
    如果不是函数调用太深,一直不退出,就是栈上变量太大,太多。比如:

    char arr[1024][1024]; //直接耗了1M

    ============================

    VC定义超大数组时,stack OverFlow的解决方法,当然了这里的数组不仅仅是int,char,double等内置类型,还可以是其他的类,如CString,CButton,CMap等。

    stack overflow,堆栈溢出
    VC超大数组Stack Overflow的解决方法


    这次在写一个程序的时候,定义了一个超大的char型数组,元素个数超过3000W个的时候,程序无法调试,提示:Stack Overflow。

    用单步调试试了一下,定义数组的时候没问题,但是在开始对数组赋值的时候,就会弹出一个Stack OverFlow的错误提示,有了程序的错误提示,那就好解决了,在百度上搜索了一下,就找到了解决方法.

    如果是英文版:
    project -> setting -> link -> category 选择 output -> stack allocations 里面的 reserve 填入 0x10000000 然后选OK

    当然了,如果还是不能解决的话,那就要用动态数组了,毕竟动态意味着无穷~~

    vc动态数组实现

    -------------------------------------------

    栈被用作存放局部变量、调用函数前存放返回地址等,vc中每个工程默认栈大小为1m,new分配的空间不在栈(stack)中,在堆(heap)中,因此不会是由于new了不delete造成的。栈溢出可能的原因是:生成了大量局部变量或使用了大的局部数组、递归函数设计不当无出口导致一直调用无法返回。可以修改栈的大小解决这个问题,修改方式如下:
    LINK的/STACK选项 :Project-->settings->link->category选output-->
    /STACK :reserve[,commit]
    reserve:栈总大小
    commit:程序开始时系统提供的实际内存量
    缺省:1M,8K
    参数为0取缺省值
    【reserve :2000000 栈被设置为2M 】

  • 相关阅读:
    C#委托本质探索 四、方法变量内、外混合调用
    calibredrv 对layer做操作
    2021年11月工作笔记
    2022年1月工作资料
    2021年12月工作资料
    MySQL 5.7 MGR原理及部署
    在虚拟机上安装redis集群,redis使用版本为4.0.5,本机通过命令客户端可以连接访问,外部主机一直访问不了
    mongoDB中的的常用语法
    使用Nginx做图片服务器时候,配置之后图片访问一直是 404问题解决
    jquery.cookie() 方法的使用(读取、写入、删除)
  • 原文地址:https://www.cnblogs.com/areliang/p/2495470.html
Copyright © 2011-2022 走看看