recursividad primo numeros numero invertir financiera ejercicios ejemplos concepto codigo c# .net recursion stack-overflow csc

c# - primo - ¿Por qué esta recursión no produce una StackOverFlowException?



recursividad financiera (4)

Qué está mal con este código:

using System; namespace app1 { static class Program { static int x = 0; static void Main() { fn1(); } static void fn1() { Console.WriteLine(x++); fn1(); } } }

Compilo este fragmento de código usando este comando:

csc /warn:0 /out:app4noex.exe app4.cs

Cuando hago doble clic en el exe, no parece arrojar la excepción (StackOverFlowException), y sigue funcionando para siempre.

Usando el símbolo del sistema de Visual Studio 2010, pero también tengo instalado el sistema operativo vs 2012, todo al día.


Cuando el programa se ejecuta en el entorno de Visual Studio, utilizará una pila limitada de profundidad. Quiero decir que cuando compilas un programa en VS2012 pulsando F5 y F6 en el teclado, enviará algunos parámetros al programa csc.exe para limitar el programa y hacer que el stack-over-flow te avise del error que está en tu programa código fuente y algoritmo. En realidad, no existe un error Stack-over-flow, el proceso del programa utilizará almacenamiento real y almacenamiento virtual y OS lo hará por usted.

Nota: también está relacionado con su sistema operativo, algunos sistemas operativos emitirán un error si son deficientes en la administración de la memoria y la programación de la CPU.


El jitter de x64 detecta esto como una llamada de cola y lo optimiza, mientras que el jitter x86 no hace esto. El jitter x64 es más agresivo sobre estas optimizaciones. Vea el análisis de Bart de Smet y la publicación del blog del equipo de CLR en él.


Existe una cosa llamada optimización recursiva de la cola .

Desde una perspectiva de pila, básicamente significa que si lo último que hace un método es llamar a otro método, la nueva llamada puede tomar el marco de pila del método de llamada. Por ejemplo en:

static void Main() { fn(0); } static void fn(int value) { fn(value+1); }

en lugar de que la pila de llamadas crezca Main->fn(0)->fn(1)->... ad nauseam, tendrá exactamente dos enlaces de longitud, primero Main->fn(0) que Main->fn(1) , hasta Main->fn(int.MaxValue) donde explotará o se desbordará.

Ahora, la pregunta es, ¿el compilador de C # realmente hace esto?
AFAIK, al usar los compiladores C # 4.0 y posteriores, cuando compila en un entorno x86, no utiliza la optimización de la cola de llamadas, y cuando compila la aplicación x64, utiliza la optimización de la cola de llamadas (y aparentemente, de los otros comentarios / respuestas que yo estoy en lo cierto). Por ejemplo, en mi sistema, usando LINQPad, el código que proporcionó explotó rápidamente con una Exception .


Porque el optimizador desenrolla la llamada de recursión de cola en:

static void fn1() { START: Console.WriteLine(x++); GOTO START; }

Reescribe para obtener excepciones como estas:

static int y; static void fn1() { Console.WriteLine(x++); fn1(); Console.WriteLine(y++); }