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.
12 Comments
-
Muchas gracias por la ayuda, no sabía como solucionar la excepción del stack overflow. Un saludo desde Tenerife,
Adolf
-
Por eso lo puse aquí, xk yo también las pasé putas con ese problema.
Saludos.
-
q mamera
-
a mi no me anda nada.. .nop
-
fransua, si esto no te funciona es muy probable que tengas alguna función recursiva que nunca retorna.
-
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 -
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.
-
Mike, porque simplemente VC#, no tiene enlazador.
-
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. -
creo que mi recursividad es muy alta ya que en algunos casos le pongo casi los 100 MB de STACK, gracias por la informacion.
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.