2008-09-24 9 views
29

¿Hay una manera de conocer y de salida del tamaño de la pila sea necesario por una función en tiempo de compilación en C? Esto es lo que me gustaría saber:Comprobación del desgaste de la pila en tiempo de compilación

Tomemos alguna función:

void foo(int a) { 
    char c[5]; 
    char * s; 
    //do something 
    return; 
} 

Al compilar esta función, me gustaría saber cuánto espacio de pila consumirá Whent que se llama. Esto podría ser útil para detectar la declaración en la pila de una estructura que oculta un gran buffer.

Busco algo que imprimir algo como esto:

archivo foo.c: Función uso de pila foo es n bytes

¿Hay una manera de no mirar a la asamblea generada saber que ? ¿O un límite que se puede establecer para el compilador?

Actualización: No estoy tratando de evitar el tiempo de ejecución de desbordamiento de pila para un proceso dado, estoy buscando una manera de encontrar antes de tiempo de ejecución, si un uso de pila función, según lo determinado por el compilador, está disponible como una salida del proceso de compilación.

Digámoslo de otra manera: ¿es posible conocer el tamaño de todos los objetos local a una función? Creo que la optimización del compilador no será mi amiga, porque algunas variables desaparecerán, pero un límite superior está bien.

+0

En caso de que se lo pregunte, escribí el carácter secreto '}' –

+0

La pregunta no me parece clara. Creo que si se escribe más sobre por qué quiere saber por qué esto y comprobar el desmontaje o ejecutable (que es la forma más fácil de comprobar la salida del compilador) no es aceptable, tal vez alguien podría encontrar alguna solución fácil? – Suma

Respuesta

10

El código de kernel de Linux se ejecuta en una pila de 4K en x86. Por eso les importa. Lo que utilizan para comprobarlo es una secuencia de comandos de perl que escribieron, que puede encontrar como scripts/checkstack.pl en un archivo kernel reciente (2.6.25 lo tiene). Se ejecuta en el resultado de objdump, la documentación de uso está en el comentario inicial.

Creo que ya lo usé para binarios de espacio de usuario hace años, y si conoce un poco de programación perl, es fácil de arreglar si está roto.

De todos modos, lo que hace básicamente es mirar automáticamente la salida de GCC. Y el hecho de que los hackers kernel escribieron tal herramienta significa que no hay una forma estática de hacerlo con GCC (o tal vez que se haya agregado recientemente, pero lo dudo).

Btw, con objdump del proyecto mingw y ActivePerl, o con Cygwin, debería ser capaz de hacerlo también en Windows y también en binarios obtenidos con otros compiladores.

+5

Actualización: Michael Greene observó a continuación que GCC 4.6 tiene -fstack-uso disponible para C: gcc.gnu.org/gcc-4.6/changes.html; -fstack-usage se describe a continuación en la respuesta de shodanex a continuación: http://stackoverflow.com/a/126490/53974. – Blaisorblade

1

Sólo el compilador sabe muy bien, ya que es el tipo que pone todas sus cosas juntos. Tendría que mirar el ensamblaje generado y ver cuánto espacio está reservado en el preámbulo, pero eso realmente no cuenta para cosas como alloca que hacen su trabajo en tiempo de ejecución.

+0

analizadores de código estáticos teóricamente tales pelusas pueden hacer el trabajo, prácticamente no creo que lo hagan. Su – Ilya

-1
No

en general. El problema de la detención en la informática teórica sugiere que no se puede predecir si un programa general se detiene en una entrada determinada. Cálculo de la pila utilizada para ejecutar un programa en general sería aún más complicado. Entonces: no. Quizás en casos especiales.

Digamos que tiene una función recursiva, cuyo nivel de recursión depende de la entrada, que puede ser de longitud arbitraria y que ya están fuera de suerte.

+0

hablando de la pila de procesos, no en la cantidad de cada llamada a la función utilizará – shodanex

+0

El problema de la parada no se detiene el análisis estático (es decir, en los compiladores), y para dar respuestas aproximadas examinado el texto del programa. De hecho, un gran desafío es la computación cuando dos programas diferentes son equivalentes, por lo que dos programas equivalentes pueden dar resultados diferentes en el análisis estático. – Blaisorblade

3

no veo por qué un análisis de código estático no podía dar una buena figura suficiente para esto.

Es trivial encontrar todas las variables locales en cualquier función dada, y el tamaño de cada variable se puede encontrar a través del estándar C (para tipos incorporados) o calculando (para tipos complejos como estructuras y uniones) .

Claro, no se puede garantizar que la respuesta sea 100% precisa, ya que el compilador puede hacer varios tipos de optimizaciones como relleno, colocar variables en registros o eliminar completamente variables innecesarias. Pero cualquier respuesta que dé debería ser, al menos, una buena estimación.

Hice una búsqueda rápida en Google y encontré StackAnalyzer pero mi conjetura es que otras herramientas de análisis de código estático tienen capacidades similares.

Si desea una cifra exacta del 100%, entonces usted tendría que mirar a la salida del compilador o comprobar que durante el tiempo de ejecución (como Ralph sugiere en his reply)

+1

StackAnalyzer parece agradable, pero no hace el trabajo solicitado, ya que analiza el ejecutable, no el código fuente. Mientras escribía estas herramientas debe ser realmente posible en teoría, yo no lo existe tal herramienta - el control de la ejecución uso de pila o en base a assemly es mucho más práctico. – Suma

+0

Acabo de decir un nombre de función, y usted sabe por qué el análisis de código estático no es suficiente para obtener el espacio de pila utilizado de una función: alloca. Tan pronto como una función lo usa (con valor no constante) no puedes hacerlo. Otra cosa ya mencionada: recursividad. – flolo

8

StackAnlyser parece examinate el código ejecutable en sí más alguna información de depuración. Lo que está descrito por this reply, es lo que estoy buscando, el analizador de pila me parece excesivo.

Algo similar a lo que existe para ADA estaría bien. Mira esta página del manual del manual de mosquito:

22,2 estático Pila de análisis de uso

Una unidad compilado con -fstack-uso, se generará un archivo extra que especifica la cantidad máxima de pila usada, en una función per base. El archivo tiene el mismo nombre base que el archivo de objeto de destino con una extensión .su. Cada línea de este archivo se compone de tres campos:

* The name of the function. 
* A number of bytes. 
* One or more qualifiers: static, dynamic, bounded. 

El segundo campo se corresponde con el tamaño de la parte conocida del marco de función.

El calificador estático significa que el tamaño del cuadro de función es puramente estático. Por lo general, significa que todas las variables locales tienen un tamaño estático. En este caso, el segundo campo es una medida confiable de la utilización de la pila de funciones.

El calificador dinámico significa que el tamaño del cuadro de función no es estático. Sucede principalmente cuando algunas variables locales tienen un tamaño dinámico. Cuando este calificador aparece solo, el segundo campo no es una medida confiable del análisis de la pila de funciones. Cuando está calificado con delimitado, significa que el segundo campo es un máximo confiable de la utilización de la pila de funciones.

+6

Esta es una vieja pregunta, pero hasta ahora, GCC 4.6 tiene -flash-use disponible para C: http://gcc.gnu.org/gcc-4.6/changes.html –

+1

@Michael Greene: ¡podría ser una respuesta! Gracias ! – shodanex

1

Suponiendo que está en una plataforma incrustada, puede encontrar que su cadena de herramientas tiene algo que hacer. Los buenos compiladores incorporados comerciales (como, por ejemplo, el compilador Arm/Keil) a menudo producen informes del uso de la pila.

Por supuesto, las interrupciones y la recursión son generalmente un poco más allá de ellos, pero le da una idea aproximada si alguien ha cometido un terrible error con un búfer de varios megabytes en la pila en alguna parte.

1

No exactamente "tiempo de compilación", pero me gustaría hacer esto como un paso posterior a la generación:

  • dejar que el enlazador crear un archivo de mapa para usted
  • para cada función en el archivo de mapa lea el parte correspondiente del ejecutable, y analizar el prólogo de la función.

Esto es similar a lo que hace StackAnalyzer, pero mucho más simple. Creo que analizar el ejecutable o el desmontaje es la manera más fácil que se puede acceder al resultado del compilador. Aunque el compilador conoce esas cosas internamente, me temo que no podrá obtenerlo (puede pedirle al proveedor del compilador que implemente la funcionalidad, o si usa el compilador de código abierto, puede hacerlo usted mismo o dejar que alguien lo haga). para ti).

Para implementar esto es necesario:

  • ser capaz de analizar el archivo de mapa
  • entender el formato del archivo ejecutable
  • saben lo que es un prólogo función puede parecerse y ser capaz de "decodificar" se

Lo fácil o difícil que esto sería depende de su plataforma de destino. (Embebido? ¿Qué arquitectura de CPU? ¿Qué compilador?)

Todo esto definitivamente se puede hacer en x86/Win32, pero si nunca hiciste algo como esto y tienes que crear todo esto desde cero, puede tomar unos días antes de que termines y tener algo funcionando .

Cuestiones relacionadas