3.2、函数递归调用引发的栈溢出

写一段最简单的无穷递归代码,如下:

#include "stdafx.h"
void f(void)
{
f();
}
int _tmain(int argc, _TCHAR* argv[])
{
f();
return ;
}

在VS编译,Debug模式下运行之,结果报错

观察下调用栈,发现栈没有破坏,但被大量的f()调用沾满,如下:

这也充分说明了,是递归调用引起了栈溢出

转到汇编,在地址栏里输入上面错误框里的地址0x011515C9

可以看到,程序是在执行一次入栈操作时,报错了

我们转到Windbg运行程序,观察下

看下相关寄存器的值

栈顶指针esp=0x000a2f78

在看下线程栈下限

栈区界限下限为0x000A1000,然而,此时esp=0x000a2f78,已经非常接近下限了。0x000a2f78-0x000A1000=0x1f78<0x2000,也就是说,限制esp已经进入到栈区的后两个保护页了,当线程访问到倒数第三个页面的的时候,系统会为倒数第二个页面调拨物理存储器,此时还会抛出EXCEPTION_STACK_OVERFLOW。

针对函数递归调用而引起的栈溢出,我们可以采用下面的方式来解决:

  • 给递归调用加上退出机制
  • 改变设计,不用递归,比如可以用循环语句替代

3.3、栈里的某缓冲区溢出

这种情况比较复杂,不好模拟,当在线程里执行的某个函数里,开辟了某个缓冲区,对这个缓冲区进行写操作溢出,刚好覆盖了ESP或EBP值时,可能触发栈溢出异常。对这种栈缓冲区溢出问题,在编写代码时要吗非常小心索引值的检测,或则用安全版本的api来进行读写。

四、总结

前面的讲的两种情况,是平时工作中常遇到,也是非常好定位和修改的。这两种情况下,一般调用栈是不会发生破坏的,当我们看到最后调用的是_chkstk,那么通常是栈里使用了超大缓冲区,如果最后是停在了汇编指令push xx或则其他有入栈操作的指令时,且我们在调用栈里明显看到某函数的递归调用,那么这就是递归调用引发的栈溢出。第三种情况要具体问题具体分析了

win32线程栈溢出问题 (二)的更多相关文章

  1. win32线程栈溢出问题 (一)

    一.什么是线程栈溢出 我们都知道,每一个win32线程都会开辟一个空间,用来临时存储线程执行时所调用的一系列函数的参数.返回地址和局部变量及其他上下文信息.这个空间就是线程的栈区.栈区的容量是有限的, ...

  2. win32线程

    win32线程 一丶什么是线程 在windows中常听到的就是线程.多线程.啊什么的. 这里介绍一下什么是线程. 1.线程是附属在进程中的一个执行实体.简而言之就是执行代码的. 2.每个进程至少有一个 ...

  3. Android线程管理(二)——ActivityThread

    线程通信.ActivityThread及Thread类是理解Android线程管理的关键. 线程,作为CPU调度资源的基本单位,在Android等针对嵌入式设备的操作系统中,有着非常重要和基础的作用. ...

  4. win32线程池代码(WinApi/C++)

    win32线程池代码(WinApi/C++) 健壮, 高效,易用,易于扩, 可用于任何C++编译器 //说明, 这段代码我用了很久, 我删除了自动调整规模的代码(因为他还不成熟)/********** ...

  5. Win32线程——优先权

    <Win32多线程程序设计>–Jim Beveridge & Robert Wiener Win32 优先权是以数值表现的,并以进程的“优先权类别(priority class)” ...

  6. juc线程池原理(二):ThreadPoolExecutor的成员变量介绍

    概要 线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析ThreadPoolExecutor类,来了解线程池的原理. ThreadPoolExecutor数据结构 Thread ...

  7. HDFS源码分析数据块复制监控线程ReplicationMonitor(二)

    HDFS源码分析数据块复制监控线程ReplicationMonitor(二)

  8. Win32 线程同步

    Win32 线程同步 ## Win32线程同步 ### 1. 原子锁 ### 2. 临界区 {全局变量} CRITICAL_SECTION CS = {0}; // 定义并初始化临界区结构体变量 {线 ...

  9. 线程池系列二:ThreadPoolExecutor讲解

    一.简介 1)线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, i ...

随机推荐

  1. 【IDEA使用技巧】(5) —— IntelliJ IDEA集成Tomcat部署Maven Web项目

    1.IntelliJ IDEA集成Tomcat部署Maven Web项目 1.1.IDEA构建Maven Web项目 使用IDEA来创建一个简单的Hello World的Maven Web项目,并使用 ...

  2. 最详细的Android SDK下载安装及配置教程

    文章转载与:https://blog.csdn.net/dr_neo/article/details/49870587 最近Neo突发神经,想要将学过的一些计算机视觉.机器学习中的算法都放到移动设备上 ...

  3. 为了防止页面重新自动加载,可以给a标签设置href="javascript:void(0);"

    <a href="javascript:void(0);"></a> <!--按照格式要求,此处的0不能省略!! 虽然省略看上去也没什么影响.但是当发 ...

  4. Gym 102055B Balance of the Force

    大意: $n$个骑士, 第$i$个骑士若加入光明阵营, 那么能力值$L_i$, 加入黑暗阵营, 能力值$D_i$. 给定$m$个限制$(u_i,v_i)$, 表示$u_i,v_i$不能在同一阵营. 求 ...

  5. Linux 中ifconfig和ip addr命令看不到ip

    解决方案: 输入 vi /etc/sysconfig/network-scripts/ifcfg-ens33 将ONBOOT权限改为yes 保存退出,按Esc,输入:wq 重启网络服务,输入 sudo ...

  6. NIO(2):Channel

    Channel可以理解为铁轨,Buffer是铁轨上的火车.铁轨的两端连接这文件描述符或者说文件的缓冲区和程序运行时的内存.借助NIO是一种更加符合OS底层文件系统的调用方式,使用NIO可以用更小的开销 ...

  7. sharepoint中的Power Shell命令创建、删除文档库列表

    ListTemplateType 枚举: 自定义列表-GenericList.文档库-DocumentLibrary.图片库-PictureLibrary.公告-Announcements.联系人-C ...

  8. Django使用LDAP

    https://github.com/python-ldap/python-ldap Quick usage example: import ldap l = ldap.initialize(&quo ...

  9. mtd交叉编译mkfs命令

    下载 mtd:ftp://ftp.infradead.org/pub/mtd-utils/ zlib:http://www.zlib.net/ lzo:http://bouchez.info/lzo. ...

  10. mysql如何让有数据的表的自增主键重新设置从1开始连续自增

    项目开发中,有些固定数据在数据表中,主键是从1自增的,有时候我们会删除一些数据, 这种情况下,主键就会不连续.如何恢复到像第一次插入数据一样主键从1开始连续增长, 这里我找到一种解决方法: 如上面一张 ...