问题描述
对C#不熟悉,想请问一下,c#中如果一个函数无限递归,会怎么样?
解决方案
解决方案二:
递归到无法分配栈内存时,程序就奔溃了呗
解决方案三:
while(true){}跟着效果应该差不多
解决方案四:
内存溢出,程序崩
解决方案五:
运行到内存溢出,然后奔溃~
解决方案六:
引用2楼u013053259的回复:
while(true){}跟着效果应该差不多
完全不一样while循环只不过是吃cpu无限递归会吃内存因为每递归一次,之前的也不会释放,依然保留着,好等你递归完了再一层一层的退出出来
解决方案七:
List<double>l=newList<double>();while(true){l.add(0.0f);}你要是说跟这个差不多还有点靠谱只往里加,永远不删除,总有内存溢出的时候
解决方案八:
func<int,int>func=null;func=c=>fun(c-1)+c;//没有退出条件intres=func(100000);
运行这个你试试看是什么效果
解决方案九:
理论上每次调用函数都会将其地址加载到堆栈上,所以都有次数限制拿个简单例子来说:staticintTest(inti){if(i<-500000){return1;}returnTest(i-1)+i;}
Test(i-1)+i因为有+i的运算,需要把上一次递归的结果暂存到一个临时变量,加载到栈上,随着次数的增加,会占用越来越多的堆栈,而线程的堆栈是有限的(默认1M)不过编译器可以优化尾递归形式(函数直接返回自身的调用),右侧改为returnTest(i-1),这样就不需要临时变量(func的地址是固定的),编译器就可以将其优化成循环,跳转到原地址,传入新的参数在工程属性中勾选“允许优化代码”后(或者Release生成),就不会溢出了,不勾选就溢出LS的代码由于没有退出条件,优化后将造成死循环
解决方案十:
一般来说结果就是StackOverflowException导致程序结束。不过具体行为不仅和程序有关,还和编译器还有jit有关。调用有一种,它可以进行优化,调用时其实当前方法已经结束,就可以先对栈进行处理再调用。这种对递归来说就是尾递归,不需要栈不停增长。IL有tail指令来通知jit尾递归,但是C#的编译器不会产生这个指令(F#的编译器会),而是jit自动根据情况优化,只有release方式编译后,在64位jit的执行才支持。clr4对尾调用又进行过。比如以下最简单的递归,如果是Release模式64位运行,就会无限循环,类似于while(true),而其它方式运行都会stackoverflowpublicstaticvoidR(){R();}
但是自己也无法确定jit会不会进行尾调用优化,而且StackOverflowException是无法catch的,会直接导致程序结束。所以数据量大时要自己根据情况控制好递归深度,避免栈溢出。或者转化成不使用递归的算法。
解决方案十一:
编译没问题,执行的时候会报错。C#递归深度有限制的。
解决方案十二:
哈,我比较好奇楼主为什么会有这么个问题怎么想“无限”递归都是件耗资源耗CPU的事,程序跑“累了”就会理所当然地崩掉,但是不会影响到系统。
解决方案十三:
引用10楼yuwenge的回复:
编译没问题,执行的时候会报错。C#递归深度有限制的。
C/C++一样的,都用的堆栈模型
解决方案十四:
堆栈溢出。你使用的局部变量越多,递归的层数越少。递归的层数没有限制,限制是堆栈的大小,默认CLR使用4MB的堆栈。
解决方案十五:
引用2楼u013053259的回复:
while(true){}跟着效果应该差不多
效果差别很大。这个会无限循环下去,但递归不会无限,而是会在栈溢出后抛出异常。
其他方案:
无限递归会导致栈溢出,系统随即抛出OverflowException
其他方案:
引用13楼caozhy的回复:
堆栈溢出。你使用的局部变量越多,递归的层数越少。递归的层数没有限制,限制是堆栈的大小,默认CLR使用4MB的堆栈。
我记得好像有次我写的递归,在运行的时候深度过深报错是“递归深度超过32层”,递归的深度应该是32层,在不进行设置的情况下
其他方案:
引用16楼ta_wuhen的回复:
Quote: 引用13楼caozhy的回复:
堆栈溢出。你使用的局部变量越多,递归的层数越少。递归的层数没有限制,限制是堆栈的大小,默认CLR使用4MB的堆栈。我记得好像有次我写的递归,在运行的时候深度过深报错是“递归深度超过32层”,递归的深度应该是32层,在不进行设置的情况下
好把,我记错了,32层是数据库里的。。。C#是堆栈溢出来结束无限递归的
其他方案:
边界不确定的情况下用递归是作死的节奏啊!无论还崩溃还是默默死循环,结果没什么本质不同,都是跑不下去了呗。