zoukankan      html  css  js  c++  java
  • [转]C++ 堆栈溢出的原因以及可行的解决方法

    栈溢出(stackoverflow)的原因及解决办法

    大家都知道,Windows程序的内存机制大概是这样的:全局变量(局部的静态变量本质也属于此范围)存储于堆内存,该段内存较大,一般不会溢出;

    函数地址、函数参数、局部变量等信息存储于栈内存,VC++6中栈内存默认大小为1M,对于当前日益扩大的程序规模而言,稍有不慎就可能出问题(动态申请的内存即new出来的内存不在栈中),即如果函数这样写:

    void test_stack_overflow()

    {

    char *pdata = new[2 * 1024 * 1024];

    delete[]pdata;

    }

    是不会出现这个错误的,而这样写则不行:

    void test_stack_overflow()

    {

    char chdata[2 * 1024 * 1024];

    }

    大多数情况下都会出现内存溢出的错误,不信在VC++6中随便做个程序,调用一下这个函数试式。

    出现栈内存溢出的常见原因有2个:

    1>函数调用层次过深,每调用一次,函数的参数、局部变量等信息就压一次栈。

    2>局部静态变量体积太大

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

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

    解决办法大致说来也有两种:

    1>增加栈内存的数目

    2>使用堆内存增加栈内存

    第一种解决办法:在VC++6种依次选择Project->Setting->Link,在Category中选择output,在Reserved中输入16进制的栈内存大小如:0x10000000,然后点ok就可以了。

    其他编译器也有类似的设置,个人认为这不是一个好办法,有一个致命原因,不知道有没有人遇到过,我把栈内存改大后,与数据库建立不了连接了(ADO方式,Acess数据库),还有遇到调用CreateThread会提示栈不够而创建线程失败,把栈内存还原,问题立刻消失。

    不知道究竟是什么原因,有知道的可以告诉我。

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

    void test_stack_overflow()

    {

    static char chdata[2 * 1024 * 1024];

    }

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

  • 相关阅读:
    Meterpreter核心命令
    bugku ctf 杂项 旋转跳跃 (熟悉的声音中貌似又隐藏着啥,key:syclovergeek)
    bugku 神秘的文件
    代码审计
    “百度杯”CTF比赛 九月场 类型:Web 题目名称:SQLi ---不需要逗号的注入技巧
    热烈祝贺北亚获批电子数据司法鉴定执业资格!
    硬盘有坏道的表现和避免硬盘坏道的方法
    如何应对eva存储崩溃的情况?
    linux系统数据恢复过程
    DELL EqualLogic PS6100恢复数据原理概述
  • 原文地址:https://www.cnblogs.com/MakeView660/p/11103591.html
Copyright © 2011-2022 走看看