C# Y EL STACK OVERFLOW

A los que llevamos ya algunos años trabajando en el mundillo del desarrollo de aplicaciones, términos como heap o stack nos son familiares.

Ahora que están de moda lenguajes de alto nivel como el C# o ActionScript, estos términos suenan difusos, como algo del pasado… y nada más lejos de la realidad.

Los que seáis de mi quinta (rondando la treintena) y tengáis los huevos pelaos de programar, seguro que habéis picado lineas de C y C++ por un tubo. Y como bien sabemos, el stack o pila es un tema que según en que entornos hay que tratar con delicadeza, sobre todo cuando echamos mano de la recursividad.

La recursividad en una poderosa técnica de programación que para los no iniciados, consiste en que una función se llame a si misma. Claros ejemplo de recursividad son el cálculo de un factorial, la serie de Fibonacci o el algoritmo de relleno FloodFill.

Que una función se llame a si misma conlleva un peligro y es que esta se quede llamándose a si misma más de lo esperado, provocando el temido Stack Overflow. En muchos casos, esto es debido a un mal diseño del algoritmo. Pero otras veces no…. necesitamos más memoria para la pila.

Si estamos programando en C o C++, esto no es excesivo problema, ya que en los settings de compilación y linkado podemos especificar memoria "extra" para la pila sin problemas.

El problema está, como en mi caso, si estamos utilizando C#.
¡¡¡No se puede cambiar el tamaño de la pila!!!

En concreto, tanto con el Runtime.NET 1.1 como el 2.0, el stack reservado para una aplicación es de algo menos de 512K's… una miseria. Un simple algoritmo de floodfill que tuviera que rellenar un área de 512×512 daría sistematicamente un StackOverflow a medio rellenar.

Aquí tenéis un simple fragmento de código en C#:


using System;
using System.Collections.Generic;
using System.Text;

// compilar con: /unsafe

namespace Recurse
{
class Program
{

static unsafe void Main(string[] args)
{
char* fib = stackalloc char[256*256*16];
}
}
}

Este simple programa realiza una reserva de 1024K's en la pila. Si compilamos y ejecutamos nos dará un StackOverflow.

Después de mucho buscar e investigar, para solucionar el problema tenemos esta solución:

Además del compilador de C#, necesitaremos el Visual C++ 7.0(.net) o superior (desconozco si esto sirve para la versión Express)
Con el Visual C viene una utilidad llamada editbin.exe. Una vez creado nuestro ejecutable (que da error), con esta aplicación le podremos cambiar el tamaño de la pila de la siguiente manera. Desde una consola tecleamos lo siguiente:

editbin /stack:4000000 Programa.exe

Con esta simple linea habremos puesto a disposición de nuestro programa casi 40Mb de Stack, con lo que podremos solucionar el problema.

A mi me ha salvado la vida…. pero no hubiera sido más fácil que microsoft hubiera puesto más settings en sus nuevos compiladores…. se ve que no.



COMENTARIOS

  1. Guti 29 diciembre 2005, 20:12

    Solo confirmar que con el VStudio 2005, también viene la utilidad editbin…

    Si no hubiera sido por tu post, nunca habría sabido ni que existía, ni para que servía.

  2. Adolf 24 abril 2006, 23:34

    Muchas gracias por la ayuda, no sabía como solucionar la excepción del stack overflow. Un saludo desde Tenerife,

    Adolf

  3. Polimalo 25 abril 2006, 21:49

    Por eso lo puse aquí, xk yo también las pasé putas con ese problema.

    Saludos.

  4. me 11 marzo 2008, 00:50

    q mamera

  5. fransua 26 abril 2008, 23:49

    a mi no me anda nada.. .nop

  6. Polimalo 28 abril 2008, 19:33

    fransua, si esto no te funciona es muy probable que tengas alguna función recursiva que nunca retorna.

  7. Diego 4 julio 2008, 10:51

    Muchas gracias por la solución. Funciona perfectamente pero me he encontrado con un caso en que no.
    El cambio de tamaño hay que realizarlo sobre el proyecto principal o ejecutable. Resulta que tengo una dll dónde realizo la llamada recursiva. Esa dll la envío a otros usuarios que la usarán en sus proyectos. El problema es que estos usuarios no tendrían por qué cambiar ningún setting de sus proyectos.
    ¿Existe alguna manera de cambiar el tamaño del stack para la dll y así evitar que los usuarios de esa dll tengan que cambiar nada?
    Saludos,
    Diego

  8. Mike 14 agosto 2008, 07:08

    EDITBIN se instala con el Visual Studio en sí, por lo que está disponible aun si sólo instalas VC#.

    Por otro lado el “setting” del stack en VC++ es una opción del linker no del compilador. ¿Porque habria MS de ponerla en el compilador de VC#?

    Saludos.

  9. PoliMalo 14 agosto 2008, 22:54

    Diego, lo que comentas de la dll no es posible, ya que el segmento de pila pertenece al ejecutable.

    Mike, buena observación.

  10. Guti 17 agosto 2008, 18:40

    Mike, porque simplemente VC#, no tiene enlazador.

  11. Eduardo 4 junio 2009, 19:12

    Hola, estoy desarrollando una aplicación para el cálculo del polinomio de Tutte en c++. El problema de este algoritmo es que es recursivo y dependiendo de los parámetros de entrada puede llegarse a profundidades que hacen que se sobrepase el umbral soportado.
    Has mencionado algo acerca de que se puede configurar el tamaño de la pila de llamadas para c++, podrías indicarme como hacerlo?
    Un saludo.

  12. Ozi 26 agosto 2011, 18:54

    creo que mi recursividad es muy alta ya que en algunos casos le pongo casi los 100 MB de STACK, gracias por la informacion.

DEJA TU COMENTARIO