递归导致的StackOverflow的分析
递归在多层次遍历时尤为重要,这里我们不讲递归的实现,来谈谈递归的内存占用情况。
如下代码,当我们运行时很简单,StackOverflowException瞬间抛出;这里确实是“瞬间”出错了,线程堆栈溢出;
首先我们要理解,一个程序是在一个进程下运行的,进程下可以有很多线程执行,但是每一个线程能占用的内存控件是有限的,大约1M,当一个线程占用超过1M时,就会StackOverflow了;存放在线程堆栈上的有方法中的值类型变量,和引用变量的指针地址。理解这些能帮我们分下,递归为什么导致StackOverflow了。
static void Main(string[] args)
{
Main(args);
}
这里我们做一个简单的分析,不考虑不重要的因素:
首先,线程执行Main方法,首先方法总没有值类型变量,只有数据args,所有只有args的指针地址存放在线程堆栈上,占4byte,Main中有调用Main方法,如此递归调用,就相当于(4+4+4……+4)bytes,最终达到1M,导致StackOverflow异常。有CLR抛出异常。
当然这里线程执行方法只是一个简单的分析,实际情况很复杂,比如,进入方法,会有一个专门的表维护方法信息,方法的返回地址,参数,局部变量,这些都占用线程堆栈空间,方法返回时,所有方法占用的内存被释放。而上述递归,永远不存在方法返回,所以资源不会被释放,最终抛出异常。
如果说上述很简单理解,那我们加俩行代码:
static void Main(string[] args)
{
GC.Collect();
GC.WaitForFullGCComplete();
Main(args);
}
这样执行方法,这个代码是我从某论坛的一个版主那里看来的,他说这样就不会导致StackOverflow了,结果下面的一群人深信不宜,我感觉递归肯定资源耗尽,只是GC不能回收线程堆栈内存,但是当我在代码上运行时,上述代码确实不报错,一直运行着,当时纳闷难道我理解错误,这不科学!我一直等着,果然过了1分钟多,我期待的StackOverflow出现了,心里窃喜。
但是我本身也不是很理解,为什么加了上面的两句话导致,要等那么久才移除,很奇怪。我问了问别人,结果实验了一下,将GC代码去掉,仅仅加一个Thread.Sleep(5),也会导致很长时间才抛出异常,费解中,最后我写了如下代码:
static int a = ;
static void Main(string[] args)
{
a++;
Console.WriteLine(++a);
Main(args);
}
我看下方法递归多少次,我电脑上是a=12万多,也就是最终方法递归了12万多次抛出了StackOverflow,所有上面的Thread.Sleep(5)执行长时间才报错也可以的出结论了,每一递归一次方法听5毫秒,递归1万次就是50秒,所以,结论不是GC回收影响递归长时间不报错,而是,每次执行GC,线程Sleep的时间,让我感觉长时间不报错。
上面问题本身没有多大意义,仅仅作为笔记记录一下,同样自己也更深入理解了内存占用。
递归导致的StackOverflow的分析的更多相关文章
- alias导致virtualenv异常的分析和解法
title: alias导致virtualenv异常的分析和解法 toc: true comments: true date: 2016-06-27 23:40:56 tags: [OS X, ZSH ...
- [转]DllMain中不当操作导致死锁问题的分析——DllMain中要谨慎写代码(完结篇)
在CSDN中发现这篇文章,讲解的比较详细,所以在这里备份一个.原文链接:http://blog.csdn.net/breaksoftware/article/details/8167641 DllMa ...
- 使用Django.core.cache操作Memcached导致性能不稳定的分析过程
使用Django.core.cache操作Memcached导致性能不稳定的分析过程 最近测试一项目,用到了Nginx缓存服务,那可真是快啊!2Gb带宽都轻易耗尽. 不过Api接口无法简单使用Ngin ...
- Mysql查询语句使用select.. for update导致的数据库死锁分析
近期有一个业务需求,多台机器需要同时从Mysql一个表里查询数据并做后续业务逻辑,为了防止多台机器同时拿到一样的数据,每台机器需要在获取时锁住获取数据的数据段,保证多台机器不拿到相同的数据. 我们My ...
- ORA-04031错误导致宕机案例分析
今天遇到一起ORACLE数据库宕机案例,下面是对这起数据库宕机案例的原因进行分析.解读.分析过程中顺便记录一下这个案例的前因后果,攒点经验值,培养一下分析.解决问题的能力. 案例环境: 操作系统 ...
- 基于.NET的大型Web站点StackOverflow架构分析(转)
Stack Overflow网址:http://stackoverflow.com/ 当前访问量:每月9500PV(每天300多万PV) 当前Alexa排名:149 所用.NET技术:C#.Visua ...
- windows phone因为墓碑化导致“正在恢复”的分析
我们在平时的WP使用过程中,会遇到一个问题 应用在切出,切回后, 有时候,会显示"正在恢复",并等待时间较长,才能回到用户切出时候的画面,但是这种情况并非常见,偶尔发生 有时候,直 ...
- HashMap-死锁导致cpu占用100%分析(转)
最近项目里面的一段千年代码出了问题,这个问题以前也出现过,不过不是那么明显,这次迁移机器由以前的4台机子变成2台以后问题被放大,最终不得不解决,特此分析一下. 先放出问题的代码 ? 1 2 3 4 5 ...
- [经验分享] MySQL Innodb表导致死锁日志情况分析与归纳【转,纯学习】
在定时脚本运行过程中,发现当备份表格的sql语句与删除该表部分数据的sql语句同时运行时,mysql会检测出死锁,并打印出日志. 两个sql语句如下: (1)insert into backup_ta ...
随机推荐
- Android Studio运行main方法
这样想做一些测试就很简单了 实现步骤如下: 1.当前项目右键->new->Module->Java Library 2.修改你创建javaLib的build.gradle文件 改为( ...
- 最简单的基于JavaEE和FFmpeg的视频网站
最简单的视频网站 Simplest Video Website 雷霄骅 Lei Xiaohua leixiaohua1020@126.com 中国传媒大学/数字电视技术 Communication U ...
- VS2017 安装过程
2017 安装过程 工欲善其事必先利其器 Visual Studio 2017 正式版官方下载地址:https://www.visualstudio.com/downloads/ 安装vs2017的时 ...
- C#中的Lambda总结
Lambda的前世今生 早在C# 1.0 时,C#中就引入了委托(delegate)类型的概念.通过使用这个类型,我们可以将函数作为参数进行传递.在某种意义上,委托可理解为一种托管的强类型的函数指针. ...
- 5 wcf双工
1 创建两个项目 Wcf_WsDual_Service Wcf_WsDual_Client 2 Wcf_WsDual_Service 项目中创建 LoginService.cs 的wcf文件 ...
- WPF MVVM模式中,通过命令实现窗体拖动、跳转以及显隐控制
原文:WPF MVVM模式中,通过命令实现窗体拖动.跳转以及显隐控制 在WPF中使用MVVM模式,可以让我们的程序实现界面与功能的分离,方便开发,易于维护.但是,很多初学者会在使用MVVM的过程中遇到 ...
- 讨论IM软件“网上假货’
概要 网上假货.在不能使用网络的情况下,IM软件还显示在线. 网上是假的"在线--当前离线"之间的状态,在这段时期.用户无法发送消息.用户可以创建假冒网上心跳的错觉(点击了解).缓 ...
- ANDROID-BOOTSTRAP开源项目使用方法
1.将程序导入到工作空间,修改target=android-XX为本地android SDK版本. 2.在项目中点击右键选择Properties->Android Library,添加ANDRO ...
- C ++ 17 技术上已经完成,C ++ 20 也在路上(有路线图)
在前不久结束的冬季 ISO C ++标准会议(Kona)上,C ++ 17 宣布在技术上已完成,仅剩下一些 ISO 相关的繁文缛节,即将提交至最终的 ISO 投票表决.该会议由 Plum Hall 和 ...
- 百度最热门31款开源项目:ECharts火爆了!
本文为大家整理了百度开源的热门项目,看看有没有感兴趣的,排名顺序按照 Github ★Star 数排列. 0.一个纯 Java 的图表库 ECharts★Star 19690 ECharts,一个纯 ...