递归导致的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的时间,让我感觉长时间不报错。
上面问题本身没有多大意义,仅仅作为笔记记录一下,同样自己也更深入理解了内存占用。
最新文章
- [转]俞敏洪:我和马云就差了8个字... [来自: news.mbalib.com]
- Some Delphi tips
- 友情提醒:欲开发android5.0以上应用,请全部更新开发工具至最新
- BLOB或TEXT字段使用散列值和前缀索引优化提高查询速度
- 精华阅读第 9 期 |滴滴出行 iOS 客户端架构演进之路
- 分布式ActiveMQ集群
- 关于Spring中AOP的理解
- 【转】android adb命令
- [LeetCode]题解(python):019-Remove Nth Node From End of List
- Netty 系列一(核心组件和实例).
- Android相关 博客收藏
- 国外优秀C/C++网站
- 《图解CSS3:核心技术与案例实战》
- 2017 年 机器学习之数据挖据、数据分析,可视化,ML,DL,NLP等知识记录和总结
- LeetCode OJ:Valid Number
- C#使用zookeeper
- 某C电面记
- springboot-5-整合jpa
- NYOJ467 中缀式变后缀式 【栈】
- maven-windows使用
热门文章
- error: openssl/md5.h: No such file or directory
- SpringCloud学习笔记-zuul网关
- delphi 10.2 创建并使用资源文件(一共22种格式,RCDATA是自定义格式)
- .net 程序员 两年工作总结
- Java transient关键字【转】
- ddraw 视频下绘图 不闪烁的方法
- matlab 矢量化编程(一)—— 计算 AUC
- WPF 使用字体引发的 CLR20r3 问题排查
- sql count(1)不要和查询数据混用 非常耗时
- php获取一个月前的时间戳,获取三个月前的时间戳,获取一年前的时间戳