Hola y bienvenidos.
En esta conferencia, quiero hablar un poco sobre la pila de llamadas, qué es exactamente y
cómo puedes leerla para ayudar a depurar tu programa.
Un seguimiento de pila, que es esencialmente lo que es la pila de llamadas, se genera cada vez que tu aplicación se
bloquea debido a un error fatal.
La razón por la que se utiliza el término pila es porque se refiere a una estructura de datos habitual en programación.
La pila es una estructura de datos conocida como LIFO, último en entrar, primero en salir, y así es como se almacenan
los datos.
El último dato que se añade es el primero que se recupera.
Es como comer una pila de tortitas: la primera tortita es la
de abajo.
La última tortita está arriba.
Cuando vas a comértelos, te comes el último que se ha añadido.
Por lo tanto, un seguimiento de la pila es muy útil cuando el programa se bloquea, ya que contiene información que le ayuda
a depurarlo.
Por lo tanto, un seguimiento de pila muestra una lista de las llamadas a funciones que conducen al error.
Y lo que sucederá es en un programa cuando se llama a su función principal, que es el punto de entrada.
La función principal va a llamar a otras funciones.
Esas funciones van a llamar a otras funciones y todas esas funciones que sean implementadas o llamadas
serán puestas en la pila.
Y así que usted puede hacer es cuando un programa se bloquea, la pila de llamadas le dirá que la última función
que se invocó y la línea específica de código que causó el error.
La pila de llamadas contiene mucha información útil.
Incluirá el nombre del archivo y los números de línea del código que provoca la excepción
o el error fatal.
La parte superior de la pila contiene la última llamada que causó el error y podría haber llamadas anidadas.
La parte inferior de la pila contiene la primera llamada que inició la cadena de llamadas para llamar al error.
Así que si por lo general en C que será en la rutina principal, se invoca el principal, el principal invoca otra función, que invoca otra
función y así sucesivamente y así sucesivamente.
Y se detalla la última línea.
Es muy, muy útil cuando app por app se cuelga.
Y así, cuando un programa C se bloquea, puede generar un fallo de segmentación y eso no te dice mucha información.
Sólo significa que ha pasado algo malo.
Esto también generará un archivo de núcleo.
Puedes analizar el archivo core que contiene la pila de llamadas, que te dirá la línea exacta
de código que causó el problema de tu fallo.
Así que necesitas encontrar la llamada en tu aplicación que está causando el fallo.
Y la pila de llamadas es probablemente la mejor forma de hacerlo.
Y no siempre es necesario consultar ese archivo central.
También puede analizar la pila de llamadas en el uso de GDB con un depurador.
Y quiero mostrarte cómo se ve esto.
Un programador también puede volcar la traza de la pila en cualquier momento.
Así, si detectas un error o reconoces que puede producirse un error fatal, puedes volcar la pila de
llamadas para ver qué está pasando.
Si en realidad no sabes cuándo se va a producir el error, aún puedes volcar la pila de
llamadas para ver las trazas actuales que condujeron a una llamada en particular.
Al utilizar GDB, la pila de llamadas tendrá un aspecto similar al siguiente.
Puedes acceder a la pila de llamadas a través del menú cuando estás ejecutando el depurador en GDB
y te voy a mostrar cómo hacerlo, pero esto es lo que parece y lo que verás aquí es que tiene un número, una
dirección y luego la función.
Esta pila de llamadas en particular aquí tiene un montón de diferentes llamadas, por lo que debe haber estado haciendo un montón de diferentes anidaciones
y un montón de diferentes llamadas a funciones.
Pero al final de la pila, en la línea 22, dice GTK main.
Eso significa que el.
Eso significa que probablemente ejecutó la función principal.
Y luego en la línea 21, parece que se ejecutó.
Tal vez una declaración dice ejecución del bucle principal.
Y entonces parece que llamó a una función llamada G principal contexto iterar.
Y dentro de esa función, es que había alguna cada vez que había otra llamada a una función de despacho
de contexto principal IAG.
Así que había una función iterar, a continuación, una función de envío, y luego los signos de interrogación en la línea
18 significa que no hay información de depuración.
No sabe lo que pasó allí.
Y por eso cuando construyes tu programa, puedes construirlo para liberarlo o construirlo con
información de depuración.
Cuando lo construyes con información de depuración, contiene información extra al compilar para que
al ejecutar, puedas mirar las pilas de llamadas.
Cuando lo liberes, construye algo para liberarlo.
El ejecutable es mucho más pequeño y puede no contener esta información.
Puede contener más signos de interrogación.
Pero esto también te dirá si invocaste alguna librería, algún programa adicional, los llamará y te dirá
la pila de llamadas desde allí.
Pero lo que esto está mostrando, de nuevo, son los diferentes eventos anidados para la llamada en la parte superior
es lo que es importante, porque eso significará lo que causó el accidente.
Así que parece que en esta pila de llamadas en particular, la actualización interna estaba causando un problema.
Y se puede ver que a partir de la línea 22 a la línea cero, que hay muchas invocaciones diferentes de código diferente.
Pero la eventual caída del programa en la línea cero llamada pilas.
También puedes mirar las pilas de llamadas mientras se ejecuta el programa para ver la información y poder rastrearla.
Así que si pones un punto de interrupción dentro de una función, depuras, ejecutas el depurador en eso.
El depurador se detendrá en ese punto de interrupción.
A continuación, puede mostrar la pila de llamadas y le dirá cómo ha llegado a esa línea de código.
Esta función fue invocada antes que esta función.
Y de nuevo, por lo general comenzará con la función principal.
También puedes cambiar a diferentes marcos si estás familiarizado con la pila y el concepto y
cómo está en la memoria, puedes mirar diferentes marcos, pero esta es una herramienta muy útil para encontrar
principalmente fallos en C, y es muy fácil de leer.
Si sólo miras la parte superior y no entiendes mucho sobre la pila de llamadas, puedes
mirar la parte superior y decir, Oh, eso es una fuente, eso es una línea de código que causó el fallo.
He aquí un bonito ejemplo que encontré en la web.
Excma.
Edu.
Eso ilustra ejemplos de pila de llamadas a funciones.
Así que si nos fijamos en un ejemplo en código como vamos a ver sólo tenemos un poco de código simple.
Los cálculos no importan realmente.
Básicamente estamos llamando a algunas funciones.
Así que tenemos esta función mogrify y esta función verdaderamente mitad y el principal va a llamar a una función mogrify
y luego va a llamar verdaderamente mitad y luego va a mogrify para que podamos ilustrar la pila de
llamadas y lo que parece en estas llamadas, básicamente, sólo el establecimiento de un punto de interrupción simple en
principal y luego mirando a la pila de llamadas a medida que avanzamos y hacer llamadas.
Así que de nuevo, vamos a familiarizarnos más con los puntos de interrupción e información como esa.
Pero sólo quiero demostrar la pila de llamadas muy rápido y en realidad vamos a dar un ejemplo más detallado de la
pila de llamadas más tarde.
Así que aquí me puse un punto de interrupción.
Puedo seguir adelante y construir y compilar esto y puedo iniciar el depurador y vamos a golpear ese punto de interrupción.
Y lo que notarás ahora es que puedes ver todo el menú del depurador aquí a la derecha en la parte inferior,
y verás la pila de llamadas.
Hagamos esto un poco más grande.
Pero justo cuando se detiene en la línea 14, aquí sólo tiene algunas sentencias de asignación y verás que
la pila de llamadas muestra main.
Si pasamos por encima de eso y vamos a la siguiente línea, en realidad podemos ver que sólo va a la línea 15 antes
de que llame a Mogrify, ¿verdad?
Y así ves que la pila de llamadas se queda con Main.
Si entramos, ahora verás que la pila de llamadas muestra Mogrify.
Así que en realidad estamos dentro de esta función.
Podemos pasar por encima de eso.
Así que ejecuta la primera línea y luego va a devolver temp.
Todavía permanece en esa función y luego regresa donde hace la impresión F en la línea 16, ves como la pila de llamadas
está cambiando.
A continuación, vamos a la línea 18, llamar a la pila sigue en principal y entramos en la verdadera función de la mitad.
Y ahora ves el cambio de la pila de llamadas donde muestra realmente la mitad de la función en la parte superior es siempre
la función que fue llamada por última vez.
Una vez más, damos un paso y ves que todavía estamos en la mitad de verdad.
Volvemos a Principal, imprimimos algo en la línea 19, pasamos a la línea 21.
De nuevo saltamos a la función modificar, que de nuevo se ve en la pila de llamadas, Saltamos, saltamos y finalmente
imprimimos el resultado final en la línea 23 y regresamos del programa.
Pero la pila de llamadas nos muestra de nuevo el orden de las funciones que están siendo invocadas de una función a la siguiente.
Así que si tienes funciones anidadas, puede ser cada vez más complicado.
La ventaja de la pila de llamadas es que si tienes una línea de código que se bloquea, digamos en la línea cuatro, tendrás una pila
de llamadas que contiene en la parte superior dónde se bloqueó la línea.
Y así se puede ver en realidad por ir a través de la pila de llamadas, lo que la línea de código fue el último
que fue invocado y que le dirá lo que la línea de código se estrelló.
Pero querrás usar esta herramienta cuando tu programa se cuelgue.
Gracias, señor.