win32线程栈溢出问题 (二)
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线程栈溢出问题 (二)的更多相关文章
- win32线程栈溢出问题 (一)
一.什么是线程栈溢出 我们都知道,每一个win32线程都会开辟一个空间,用来临时存储线程执行时所调用的一系列函数的参数.返回地址和局部变量及其他上下文信息.这个空间就是线程的栈区.栈区的容量是有限的, ...
- win32线程
win32线程 一丶什么是线程 在windows中常听到的就是线程.多线程.啊什么的. 这里介绍一下什么是线程. 1.线程是附属在进程中的一个执行实体.简而言之就是执行代码的. 2.每个进程至少有一个 ...
- Android线程管理(二)——ActivityThread
线程通信.ActivityThread及Thread类是理解Android线程管理的关键. 线程,作为CPU调度资源的基本单位,在Android等针对嵌入式设备的操作系统中,有着非常重要和基础的作用. ...
- win32线程池代码(WinApi/C++)
win32线程池代码(WinApi/C++) 健壮, 高效,易用,易于扩, 可用于任何C++编译器 //说明, 这段代码我用了很久, 我删除了自动调整规模的代码(因为他还不成熟)/********** ...
- Win32线程——优先权
<Win32多线程程序设计>–Jim Beveridge & Robert Wiener Win32 优先权是以数值表现的,并以进程的“优先权类别(priority class)” ...
- juc线程池原理(二):ThreadPoolExecutor的成员变量介绍
概要 线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析ThreadPoolExecutor类,来了解线程池的原理. ThreadPoolExecutor数据结构 Thread ...
- HDFS源码分析数据块复制监控线程ReplicationMonitor(二)
HDFS源码分析数据块复制监控线程ReplicationMonitor(二)
- Win32 线程同步
Win32 线程同步 ## Win32线程同步 ### 1. 原子锁 ### 2. 临界区 {全局变量} CRITICAL_SECTION CS = {0}; // 定义并初始化临界区结构体变量 {线 ...
- 线程池系列二:ThreadPoolExecutor讲解
一.简介 1)线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, i ...
随机推荐
- 【LEETCODE】55、数组分类,适中级别,题目:79、611、950
第950题,这题我是真的没想到居然会说使用队列去做,大神的答案,拿过来瞻仰一下 package y2019.Algorithm.array; import java.util.HashMap; imp ...
- git 学习笔记 ---撤销修改
自然,你是不会犯错的.不过现在是凌晨两点,你正在赶一份工作报告,你在readme.txt中添加了一行: $ cat readme.txt Git is a distributed version co ...
- go 学习笔记(3)benchmark
benchmark函数以benchmark开头 benchmark的case一般会跑b.N次,且每次执行都如此 在执行过程中会根据实际case的执行时间是否稳定会增加b.N的次数以达到稳态. pack ...
- Centos 7系统在线安装docker
在线安装docker 以下操作步骤均在root用户下操作 1. 检查内核是否符合要求 Docker 要求 Centos系统的内核版本高于 3.10 ,建议在Centos 7版本命令如下: uname ...
- 【转】webpack4安装过程遇到的问题及处理方法
随便百度一下,安装使用webpack的教程铺天盖地,安装一步步来,最后的最后打包没反应......,浪费了不少的时间. 这里我要提醒一下,如果安装webpack1,2,3按照百度上的教程应该不会有问题 ...
- C# vb .net实现不透明度调整特效滤镜
在.net中,如何简单快捷地实现Photoshop滤镜组中的不透明度调整呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第 ...
- Python接口自动化基础---session关联接口
登录一个系统之后,如果需要在登录状态下进行一些操作,那么需要怎样保持会话呢? 可以使用Session() 举例如下: import requests s=requests.Session() url1 ...
- Eclipse开发环境(二):配置
二.高级设置 1. 工作空间 在打开软件时,会提示用户选择工作空间,之后在Eclipse中创建的项目都会保存在这个工作空间(目录)下面. 在此把工作空间定为D:\workspaces\eclipse- ...
- java后台获取微信小程序openid
一.jar包准备 1.在网盘下载 链接:https://pan.baidu.com/s/15HAAWOg_yn768g4s9IrcPg 提取码:hgj0 二.在pom文件中添加依赖 1.将外部的引入的 ...
- Ruby开发小记
基础点 1.log打印 puts "Hello!" 2.拼接字符 value1 = "today" value2 = "#{value1} is Th ...