0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

堆栈溢出定义和处理方式

要长高 来源:zedware.github.io 作者:张文亮 2022-06-10 16:46 次阅读

文章中用到的示例程序:stack.zip 。

顾名思义,stack overflow 就是是栈溢出了。在进行数值运算时,我们常常要和运算结果的溢出打交道。数值运算结果可能上溢(overflow),也可能是下溢(underflow)。不过栈的溢出显然只可能是上溢,即栈空间被用完了。在提起“栈”(stack)这个概念的时候,千万不要忘记了它的兄弟“堆”(heap),也要切记不要把二者搞混了。

那么,什么时候会把给用完了呢?如果我们记得C程序中的局部变量是在栈中分配的,函数调用会占用一部分栈空间,则可以很容易地构造出相应的测试用例。

1、定义占用空间过大的局部变量所导致的栈溢出

C:\》 more stack_local.c

/*

* Allocate too much memory from stack will cause stack overflow.

*/

#include

int main(int argc, char *argv[])

{

int foo[1000000];

return 0;

}

C:\》 cl stack_local.c

Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86

Copyright (C) Microsoft Corporation. All rights reserved.

stack_local.c

Microsoft (R) Incremental Linker Version 8.00.50727.42

Copyright (C) Microsoft Corporation. All rights reserved.

/out:stack_local.exe

stack_local.obj

C:\》 stack_local

此时出现一个异常对话框:stack-local.jpg 。

2、函数递归调用导致的栈溢出

C:\》 more stack_recursive.c

/*

* Infinite recursive calls will lead to stack overflow soon.

*/

#include

static void foo(void);

static void bar(void);

int main(int argc, char *argv[])

{

foo();

return 0;

}

static void foo(void)

{

bar();

}

static void bar(void)

{

foo();

}

C:\》 cl stack_recursive.c

Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86

Copyright (C) Microsoft Corporation. All rights reserved.

stack_recursive.c

Microsoft (R) Incremental Linker Version 8.00.50727.42

Copyright (C) Microsoft Corporation. All rights reserved.

/out:stack_recursive.exe

stack_recursive.obj

C:\》 stack_recursive

该程序没声没息就结束了。查看进程返回值能发现它其实是异常终止了。只不过没有像 stack_local 那样弹出一个对话框。

C:\》 echo %errorlevel%

-1073741819

要搞清楚这两个程序为什么有这点细微的区别,可以查阅一下二者的汇编代码。原来是 _chkstk() 在起作用,其中 stack_local 在程序初始加载时就会导致 _chkstk() 失败,触发异常。而 stack_recursive 可以正确加载,并运行一段时间,然后导致栈溢出,并触发异常。

要正确处理栈溢出采用以下办法:

(1)修正我们的程序,不要造成无穷递归或太深的递归。我们可以把某些递归代码非递归化,例如那个经典的 qsort ,最好就用非递归的算法来实现,就比较皮实一点。

(2)修正我们的程序,不要定义过大的局部变量,特别是在定义大结构、大数组时要格外小心。有时我们可能会用 _alloca() 这样的特殊函数直接在栈上分配空间,更要多加注意。

(3)利用编译器的特性,将进程允许的栈大小设置得大一些。例如可以采用 MSC 中的 /STACK 参数开关。

(4)对于那些还可能导致栈溢出的代码,采用 Microsoft 的结构化异常处理或标准的 C++ 异常处理机制,结合 _resetstkoflw() 进行处理。当然了,要是不嫌麻烦,我们也可以自己探测所用栈的大小,动态地检测是否可能导致栈溢出,以避免可能的异常。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 堆栈
    +关注

    关注

    0

    文章

    182

    浏览量

    19762
收藏 人收藏

    评论

    相关推荐

    Embedded Studio堆栈溢出预防功能

    为了识别运行的嵌入式系统中的堆栈溢出问题,SEGGER编译器通过为每个函数生成检测代码的方式来检查堆栈溢出。该功能可以使用命令行开关-mst
    发表于 07-14 11:08 618次阅读

    什么是堆栈溢出?如何分配堆栈空间大小?

    前些日子bug交流群里的小哥调试了一个堆栈溢出的bug,动不动数据就被篡改了,应该也是搞得焦头烂额,头皮发麻!当时bug菌看了下,于是抛出了自己的一些调试经验,一般这样的问题80%是越界和堆栈
    的头像 发表于 11-08 09:52 4560次阅读
    什么是<b class='flag-5'>堆栈</b><b class='flag-5'>溢出</b>?如何分配<b class='flag-5'>堆栈</b>空间大小?

    TLE9893如何配置堆栈溢出检测?

    目的: 因此,根据我的理解,警戒带的下限为0x18002 320 ,而上限为0x18002 390,总共为112字节。 现在,正如链接器报告的那样,最大堆栈使用量至少为 144 字节: 因此,可以得出结论,堆栈指针必须位于我
    发表于 01-19 06:11

    PCB过孔阻焊的处理方式

    `请问PCB过孔阻焊的处理方式有哪些?`
    发表于 12-31 15:28

    FreeRTOS中的任务堆栈溢出检测机制

    余多少空间,如果函数返回0则说明可能发生了任务堆栈溢出。在应用中调用该函数可以帮助了解任务堆栈的一个实际使用情况。FreeRTOS中还提供了两种堆栈
    发表于 10-15 13:51

    按键消抖都有哪些处理方式

    按键消抖都有哪些处理方式除了硬件消抖电路用软件怎么实现
    发表于 11-01 07:06

    MSP430 C语言编程的程序堆栈溢出分析

    MSP430 C语言编程的程序堆栈溢出分析
    发表于 05-16 15:04 40次下载

    光盘销毁机的处理方式

    光盘销毁机的处理方式         
    发表于 12-31 10:50 4197次阅读

    堆栈溢出怎么解决方式

     堆栈是一个在计算机科学中经常使用的抽象数据类型。堆栈中的物体具有一个特性: 最后一个放入堆栈中的物体总是被最先拿出来, 这个特性通常称为后进先出(LIFO)队列。 堆栈
    发表于 11-28 11:16 3w次阅读
    <b class='flag-5'>堆栈</b><b class='flag-5'>溢出</b>怎么解决<b class='flag-5'>方式</b>

    cad堆栈溢出的原因及解决方式

    近期有用户反馈在打开AutoCad 2007的时候频繁出现卡死的情况,并提示还提示0x00000FD堆栈溢出,重启电脑和重装软件都无法解决。针对该问题小编整理了一些方法供大家参考。
    发表于 11-28 14:19 2.8w次阅读
    cad<b class='flag-5'>堆栈</b><b class='flag-5'>溢出</b>的原因及解决<b class='flag-5'>方式</b>

    【经验分享】系统常用 (电磁兼容)EMC处理方式

    【经验分享】系统常用 (电磁兼容)EMC处理方式
    发表于 04-17 10:02 35次下载
    【经验分享】系统常用 (电磁兼容)EMC<b class='flag-5'>处理方式</b>

    关于堆栈溢出技术你知道多少?

    虽然溢出在程序开发过程中不可完全避免,但溢出对系统的威胁是巨大的,由于系统的特殊性,溢出发生时攻击者可以利用其漏洞来获取系统的高级权限root,因此本文将详细介绍堆栈
    的头像 发表于 07-04 16:42 6392次阅读

    STM32 堆栈溢出检测

    释放,存放函数调用,局部变量等数据。堆heap用于动态内存分配。堆栈可以在启动文件或者链接脚本中指定大小,但在实际开发中,尤其工程量较大的项目中难以确定堆栈使用量,容易造成堆栈溢出,造
    发表于 12-27 18:32 22次下载
    STM32 <b class='flag-5'>堆栈</b><b class='flag-5'>溢出</b>检测

    PCB电镀中异常处理方式

    个人收集的一些异常处理方式
    发表于 08-11 15:01 0次下载

    Embedded Studio堆栈溢出预防简析

    为了识别运行的嵌入式系统中的堆栈溢出问题,SEGGER编译器通过为每个函数生成检测代码的方式来检查堆栈溢出
    的头像 发表于 07-14 11:07 937次阅读