2010-04-17 18 views
10

¿Existe un límite en el tamaño stack de un proceso en Linux? ¿Es simplemente dependiente del RAM de la máquina? Quiero saber esto para limitar la profundidad de las llamadas recursivas a una función.¿Hay un límite de tamaño de pila de un proceso en Linux

Gracias.

+0

siempre puede juntar una prueba rápida para ver qué tan profunda es la pila. CountDepth (int d) {CountDepth (d + 1); } – Martin

+2

@Martin: aunque la "profundidad" disminuye cuando realmente haces algo en la función, con variables. – GManNickG

+0

eso es cierto, pero es una buena estimación. si realmente lo desea, puede contar el número de bits en uso en variables temporales y parámetros de método y resolverlo exactamente para una función determinada – Martin

Respuesta

22

La pila normalmente está limitada por un límite de recursos. Se puede ver lo que los ajustes por defecto son en su instalación mediante ulimit -a:

stack size    (kbytes, -s) 8192 

(esto demuestra que la mía es de 8 MB, que es enorme).

Si elimina o aumenta ese límite, aún no podrá usar toda la RAM en la máquina para la pila: la pila crece hacia abajo desde un punto cercano a la parte superior del espacio de direcciones de su proceso, y en algunos punto que se ejecutará en su código, montón o bibliotecas cargadas.

+1

"en algún momento se ejecutará en su código, pila o bibliotecas cargadas" Dudo si eso sería un problema en sistemas de 64 bits como Linux x86_64? –

+0

@SamWatkins: Correcto - esta respuesta fue escrita hace 5 años, y estaba en el contexto de entornos de 32 bits. – caf

+0

Esto es incorrecto para 'i386' si [su ABI] (http://www.sco.com/developers/devspecs/abi386-4.pdf) es de creer. En él, la pila se encuentra debajo de todo lo demás y teóricamente puede crecer un poco más de '128MiB'. En ['AMD64' ABI] (https://www.uclibc.org/docs/psABI-x86_64.pdf), crece desde debajo de la marca' 128GiB', justo debajo de las bibliotecas compartidas. Por lo tanto, teóricamente puede sobrescribir código/datos, pero solo del programa principal o su montón. –

5

El límite lo puede establecer el administrador.

Ver man ulimit.

Probablemente haya un valor predeterminado que no se puede cruzar. Si tiene que preocuparse por los límites de la pila, yo diría que necesita replantear su diseño, ¿tal vez escribir una versión iterativa?

+1

O simplemente escriba una versión recursiva que use una pila administrada manualmente en lugar de la pila de llamadas a funciones. –

+2

@Roger Pate: Esa es básicamente la versión iterativa. – slebetman

3

Depende en gran medida de la arquitectura en la que se encuentre (32 o 64 bits) y si es multiproceso o no.

De forma predeterminada, en un único proceso de subprocesos, es decir, el subproceso principal creado por el sistema operativo en la hora de exec(), la pila generalmente crecerá hasta que llegue a otra cosa en el espacio de direcciones. Esto significa que generalmente es posible, en una máquina de 32 bits, tener, digamos 1G de stack.

Sin embargo, este NO es el caso en un proceso multiproceso de 32 bits. En procesamientos multiproceso, las pilas comparten espacio de direcciones y, por lo tanto, deben asignarse, por lo que normalmente reciben una pequeña cantidad de espacio de direcciones (por ejemplo, 1M) para que se puedan crear muchos hilos sin agotar el espacio de direcciones.

Así que en un proceso multiproceso, es pequeño y finito, en un único subproceso, es básicamente hasta que tocas algo más en el espacio de direcciones (que el mecanismo de asignación predeterminado intenta no pasar demasiado pronto).

En una máquina de 64 bits, por supuesto, hay mucho más espacio de direcciones para jugar.

En cualquier caso, siempre puede quedarse sin memoria virtual, en cuyo caso obtendrá un SIGBUS o SIGSEGV o algo así.

0

habría comentado la respuesta aceptada, pero al parecer necesito más rep ....

Es cierto desbordamiento de pila puede ser sutil y no siempre causar algún mensaje de error o advertencia. Acabo de tener una situación en la que el único síntoma era que las conexiones de socket fallarían con extraños errores de SSL. Todo lo demás funcionó bien. Los subprocesos podrían malloc(), bloqueos, hablar con el DB, etc. Pero las conexiones nuevas fallarían en la capa SSL.

Con restos de pila dentro de GnuTLS, estaba bastante confundido acerca de la verdadera causa. Casi informaron las huellas a su equipo después de pasar mucho tiempo tratando de resolverlo.

Eventualmente se encontró que el tamaño de la pila se estableció en 8Mb e inmediatamente después de elevarlo los problemas desaparecieron. Bajar la pila a 8Mb trajo el problema de vuelta (ABA).

Así que si está solucionando problemas que parecen ser errores de socket extraños sin ninguna otra advertencia o errores de memoria no inicializados ... podría ser un desbordamiento de la pila.

+1

¿No debería la pila seguir bloques no mapeados/no escribibles (arriba y abajo), para evitar tal carnicería? Si estoy en lo cierto, ¿cómo puede un desbordamiento de pila no causar un fallo SEGV o similar? Sugiero que la causa de tu error podría haber sido otra cosa, y el cambio de pila lo solucionó por coincidencia (cuasi-heisenbug). –

Cuestiones relacionadas