堆栈溢出怎么解决方式

堆栈溢出怎么解决方式,第1张

        堆栈

  堆栈是一个在计算机科学中经常使用的抽象数据类型。堆栈中的物体具有一个特性: 最后一个放入堆栈中的物体总是被最先拿出来, 这个特性通常称为后进先出(LIFO)队列。 堆栈中定义了一些 *** 作。 两个最重要的是PUSH和POP。 PUSH *** 作在堆栈的顶部加入一 个元素。POP *** 作相反, 在堆栈顶部移去一个元素, 并将堆栈的大小减一。

         堆栈溢出

  堆栈溢出的产生是由于过多的函数调用,导致调用堆栈无法容纳这些调用的返回地址,一般在递归中产生。堆栈溢出很可能由无限递归(Infinite recursion)产生,但也可能仅仅是过多的堆栈层级。

  堆栈溢出就是不顾堆栈中分配的局部数据块大小,向该数据块写入了过多的数据,导致数据越界,结果覆盖了别的数据。 可以理解为 在长字符串中嵌入一段代码,并将过程的返回地址覆盖为这段代码的地址,这样当过程返回时,程序就转而开始执行这段自编的代码了。

       比如如下这段程序:

  #include《stdio.h》

  int main()

  {

  char name[8];

  printf(“Please type your name:”);

  gets(name);

  printf(“Hello.%s!”,name);

  return 0;

  }

  编译并且执行,输入ipxodiAAAAAAAAAAAAAAAA,执行完gets(name)之后,堆栈如下:

  内存底部 内存顶部

  name EBP ret

  《-------[ipxodiAA][AAAA][AAAA]。。。。。。。。。。。。

  ^&name

  堆栈顶部 堆栈底部

  由于我们输入的name字符串太长,name数组容纳不下,只好向内存顶部继续写‘A’,如果提前申请动态内存就可以避免堆栈溢出。而此例由于堆栈的生长方向与内存的生长方向相反,这些‘A’覆盖了堆栈的老的元素。’EBP ret’都被‘A’覆盖了。在main返回的时候,就会把‘AAAA’的ASCII码:0x41414141作为返回地址,CPU会试图执行0x41414141处的指令,结果出现错误。这就是一次堆栈溢出!

  VS 堆栈溢出的解决方案

  方法一 : 不静态分配,用new动态创建,从堆中分配的,堆的空间足够大。

  不过记得写析构函数,delete你申请的堆空间。其实这样也挺方便,类结束的时候会自动调用析构函数释放空间。养成“不在栈上定义大数组/大对象”的好习惯很重要,否则再大的栈也会被撑爆的。

  当然,如果你不喜欢new,delete的话,还是静态分配(毕竟静态分配有很多好处),那么可以通过改变默认栈空间来解决。

  方法二 :STACKSIZE 定义.def文件

  语法:STACKSIZE reserve[,commit]

  reserve:栈的大小;commit:可选项,与 *** 作系统有关,在NT上只一次分配物理内存的大小

  方法三 :设定Visual Stdio 的/STACK 大小

  1 VC6.0修改:

  打开工程,依次 *** 作菜单如下:Project-》SetTIng-》Link,在Category 中选中Output,然后在Reserve中设定堆栈的最大值和commit。

  注意:reserve默认值为1MB,最小值为4Byte;commit是保留在虚拟内存的页文件里面,它设置的较大会使栈开辟较大的值,可能增加内存的开销和启动时间。

  2 VS2008修改

  在 Visual Studio 开发环境中设置此链接器Linker选项

  · 右键打开项目的“属性页”对话框。有关详细信息,请参见设置 Visual C++++ 项目属性。

  · 单击“链接器Linker”文件夹。

  · 单击“系统 System”属性页。

  · 修改下列任意一个(都该也可以)属性:

  · 堆栈提交大小Stack Reserve Size 100000000;

  · 堆栈保留大小Stack Commit Size 100000000.

  堆栈溢出怎么解决方式,堆栈溢出怎么解决方式 ,第2张

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/dianzi/2717513.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-08-17
下一篇 2022-08-17

发表评论

登录后才能评论

评论列表(0条)

保存