para gccwindows descargar compiler c stack mingw

gccwindows - Verificando el tamaño de pila disponible en C



gnu c++ compiler windows (9)

En Linux, debe llamar a getrusage y verificar el miembro ru_isrss de struct rusage devuelto (tamaño de pila no compartida integral).

Desde el sitio de MINGW y el seguimiento de parches realizado por el sitio de sourceforge, veo que en mayo de 2008 se realizaron algunos parches en torno a getrusage y parece que en general se admitió durante bastante tiempo. Debe comprobar cuidadosamente si hay alguna advertencia en cuanto a qué parte de la funcionalidad típica de Linux es compatible con MinGW.

Estoy usando MinGW con GCC 3.4.5 (mingw-especial vista r3).

Mi aplicación C usa mucha pila, así que me pregunto si hay alguna forma de que pueda determinar de manera programática cuánto queda de pila para poder manejar la situación de forma limpia si descubro que estoy a punto de terminar.

Si no, ¿de qué otra forma trabajarías para resolver el problema de la posibilidad de quedarte sin espacio en la pila?

No tengo idea del tamaño de la pila con la que comenzaré, así que también debería identificarla programáticamente.


Este es un problema que he abandonado. Con una gran cantidad de piratería y (principalmente) rezando, puede obtener una solución que funcione en un momento dado en una máquina determinada. Pero, en general, parece que no hay una forma decente para hacer esto.

Deberá obtener la posición y el tamaño de la pila fuera de su programa (en Linux puede obtenerlo de /proc/<pid>/maps ). En tu programa debes probar de alguna manera dónde estás en la pila. Usar variables locales es posible, pero no hay una garantía real de que estén realmente en la pila. También puede intentar obtener el valor del registro del puntero de la pila con algún ensamblaje.

Entonces ahora tienes la ubicación de la pila, su tamaño y la posición actual, y supones que sabes en qué dirección crece la pila. ¿Cuándo vas en modo desbordamiento de pila? Es mejor que no lo haga cerca del final porque su estimación (es decir, la dirección de la variable local o el valor del puntero de la pila) es probablemente demasiado optimista; no es raro dirigir la memoria más allá del puntero de la pila. Además, no tiene ni idea de cuánto espacio en la pila necesita una función determinada (y las funciones que llama). Así que tendrás que dejar bastante espacio al final.

Solo puedo aconsejarte que no entres en este lío e intentes evitar recursiones muy profundas. También es posible que desee aumentar el tamaño de su pila; en Windows, tienes que compilar esto en el ejecutable, creo.


Para Windows: he hecho esto antes de usar la función VirtualQuery de Kernel32.dll. Solo tengo un ejemplo en C # pero demuestra la técnica:

public static class StackManagement { [StructLayout(LayoutKind.Sequential)] struct MEMORY_BASIC_INFORMATION { public UIntPtr BaseAddress; public UIntPtr AllocationBase; public uint AllocationProtect; public UIntPtr RegionSize; public uint State; public uint Protect; public uint Type; }; private const long STACK_RESERVED_SPACE = 4096 * 16; public unsafe static bool CheckForSufficientStack(UInt64 bytes) { MEMORY_BASIC_INFORMATION stackInfo = new MEMORY_BASIC_INFORMATION(); UIntPtr currentAddr = new UIntPtr(&stackInfo); VirtualQuery(currentAddr, ref stackInfo, sizeof(MEMORY_BASIC_INFORMATION)); UInt64 stackBytesLeft = currentAddr.ToUInt64() - stackInfo.AllocationBase.ToUInt64(); return stackBytesLeft > (bytes + STACK_RESERVED_SPACE); } [DllImport("kernel32.dll")] private static extern int VirtualQuery(UIntPtr lpAddress, ref MEMORY_BASIC_INFORMATION lpBuffer, int dwLength); }

Por cierto: Este código también se puede encontrar en en otra pregunta que hice cuando estaba tratando de corregir un error en el código: operación aritmética resultó en un desbordamiento en inseguro C # ingrese la descripción del enlace aquí


Quitar la dirección de una variable local de la pila funcionaría. Luego, en una llamada más anidada, puede restar la dirección de otro local para encontrar la diferencia entre ellos

size_t top_of_stack; void Main() { int x=0; top_of_stack = (size_t) &x; do_something_very_recursive(....) } size_t SizeOfStack() { int x=0; return top_of_stack - (size_t) &x; }

Si su código es de subprocesos múltiples, debe ocuparse de almacenar la variable top_of_stack por subproceso.


Raymond Chen ( The Old New Thing ) tiene una buena respuesta a este tipo de preguntas:

Si tiene que preguntar, probablemente esté haciendo algo mal.

Aquí hay algunos detalles de Win32 sobre la asignación de la pila: MSDN .

Si cree que puede estar limitado por el espacio de la pila, es casi seguro que estará limitado por la memoria virtual disponible, en cuyo caso, tendrá que encontrar una solución diferente.

¿Qué estás tratando de hacer exactamente?


Suponiendo que conozca el tamaño de la pila completa, probablemente pueda agregar algún código de ensamblaje para leer ESP.
Si lee ESP y lo guarda en la función principal, puede comparar el ESP actual con el ESP que tiene en main y ver cuánto ha cambiado el ESP. Eso te dará una indicación de cuánta pila estás utilizando.


comprueba si tu compilador es compatible con stackavail ()


tal vez esto ayude solo para la plataforma de Windows:

en el encabezado PE (IMAGE_NT_HEADERS) de su exe hay algunos registros como:

typedef struct _IMAGE_NT_HEADERS { DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER32 OptionalHeader; } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; typedef struct _IMAGE_OPTIONAL_HEADER { ... DWORD SizeOfStackReserve; DWORD SizeOfStackCommit; ... }

Hay una manera simple de obtener estos valores: el uso de GetModuleHandle (NULL) le dará la base de datos (identificador) de su módulo, dirección donde encontrará una estructura IMAGE_DOS_HEADER que le ayudará a encontrar la estructura IMAGE_NT_HEADERS (imagebase + IMAGE_DOS_HEADER. e_lfanew) -> IMAGE_NT_HEADERS, y allí encontrará los campos: SizeOfStackReserve y SizeOfStackCommit .

La cantidad máxima de espacio que el sistema operativo asignará a su pila es SizeOfStackReserve.

Si consideras intentar esto, házmelo saber y te ayudaré. Hay una manera de obtener el tamaño de la pila utilizada en un cierto punto.


La función getrusage te proporciona el uso actual. (ver man getrusage ).

El getrlimit en Linux ayudaría a recuperar el tamaño de la pila con el parámetro RLIMIT_STACK .

#include <sys/resource.h> int main (void) { struct rlimit limit; getrlimit (RLIMIT_STACK, &limit); printf ("/nStack Limit = %ld and %ld max/n", limit.rlim_cur, limit.rlim_max); }

Por favor, eche un vistazo a man getrlimit . La misma información podría ser obtenida por ulimit -s o ulimit -a fila de tamaño de pila. También eche un vistazo a la función setrlimit que permitiría establecer los límites. Pero como se menciona en las otras respuestas, si necesita ajustar la pila, entonces probablemente debería reconsiderar su diseño. Si quieres una gran matriz ¿por qué no tomar la memoria del montón?