Red de conocimiento informático - Conocimiento informático - Cómo determinar la dirección dbx terminada con señal SEGV sin mapeo

Cómo determinar la dirección dbx terminada con señal SEGV sin mapeo

Utilice el depurador dbx

Depurar un programa por uno de los siguientes motivos:

Para determinar la ubicación del programa y la causa del bloqueo. Los métodos para determinar la causa del bloqueo incluyen:

Ejecute el programa en dbx y dbx informará dónde ocurrió el bloqueo.

Inspeccione el archivo de volcado de núcleo y vea el seguimiento de la pila (consulte Examinar el archivo de volcado de núcleo y ver la pila de llamadas).

Determinar por qué un programa produce resultados erróneos. Los métodos incluyen:

Establezca puntos de interrupción que detengan la ejecución para que pueda examinar el estado del programa y ver los valores de las variables (consulte Establecer puntos de interrupción y examinar variables).

Ejecute el código fuente una línea a la vez para monitorear los cambios en el estado del programa (consulte Ejecución del programa en un solo paso).

Busque pérdidas de memoria o problemas de administración de memoria. Realice comprobaciones de tiempo de ejecución para detectar errores de tiempo de ejecución (como errores de acceso a la memoria y errores de pérdida de memoria) y supervise el uso de la memoria (consulte Búsqueda de problemas de acceso a la memoria y pérdidas de memoria).

Examine el archivo de volcado de núcleo

Para determinar dónde ocurrió un fallo del programa, es posible que necesite examinar el archivo de volcado de núcleo, que es una imagen de la memoria en el momento en que el programa falló. . Puede utilizar el comando Where (consulte Comando Where) para determinar dónde se estaba ejecutando un programa cuando se volcó el núcleo.

Nota: dbx no puede mostrar el estado de una aplicación Java a través de un archivo de volcado de núcleo como lo hace el código nativo.

Para depurar un archivo de volcado de núcleo, escriba:

$ dbx program_name core

o

$ dbx - core

En el siguiente ejemplo, el programa falló debido a un error de segmentación y descartó el núcleo. El usuario inicia dbx y carga el archivo de volcado del núcleo. Luego, el seguimiento de la pila se muestra usando el comando donde, que muestra que el bloqueo ocurrió en la línea 9 del archivo foo.c.

dbx a.out core

Leer a.out

Encabezado del archivo principal leído correctamente

Leer ld.so 1

Leer libc.so.1

Leer libdl.so.1

Leer libc_psr.so.1

El programa finaliza debido a la señal SEGV (la dirección de falla no está asignada)

La función actual es principal

9 printf("la cadena 's' tiene d caracteres de longitud\n", msg, strlen( msg ));

(dbx) donde

[1] strlen(0x0, 0x0, 0xff337d24, 0x7efefeff, 0x, 0xff0000), en

0xff2b6dec< / p>

=gt;[2] main(argc = 1, argv = 0xffbef39c), línea 9 en "foo.c"

(dbx)

relacionado Para obtener más información Para obtener información sobre la depuración de archivos de volcado de núcleo, consulte Depuración de archivos de volcado de núcleo. Para obtener más información sobre cómo trabajar con la pila de llamadas, consulte Ver la pila de llamadas.

Nota: si un programa está vinculado dinámicamente a una biblioteca habilitada para ****, es mejor depurar el archivo de volcado de núcleo en el entorno operativo en el que se creó la biblioteca. Para obtener información sobre cómo depurar archivos de volcado de núcleo creados en diferentes entornos operativos, consulte Depuración de archivos de volcado de núcleo no coincidentes.

Establecer puntos de interrupción

Un punto de interrupción es un punto en el programa donde desea detener temporalmente la ejecución del programa y dejar que dbx lo controle. Establezca puntos de interrupción donde sospeche de un error del programa. Si su programa falla, determine dónde ocurre la falla y establezca un punto de interrupción antes de esa sección de código.

Cuando el programa se detiene en un punto de interrupción, puedes examinar el estado del programa y los valores de las variables. Puede establecer muchos tipos de puntos de interrupción usando dbx (consulte Detener un proceso con Ctrl C).

El tipo de punto de interrupción más simple es el punto de interrupción de parada. Puede establecer un punto de interrupción que detenga una función o procedimiento. Por ejemplo, para detener cuando se llama a la función principal:

(dbx) detener en principal

(2) detener en principal

Más sobre la parada en comando Para obtener información, consulte Configuración de puntos de interrupción de parada en funciones y el comando de parada.

También puedes establecer un punto de interrupción de parada en una línea específica de código fuente. Por ejemplo, para detenerse en la línea 13 del archivo fuente t.c:

(dbx) detenerse en t.c: 13

(3) detenerse en "t.c": 13

Para obtener más información sobre el comando detener en, consulte Configuración de puntos de interrupción de parada en las líneas de origen y el comando detener.

Puede utilizar el comando file para configurar el archivo actual y el comando list para enumerar las funciones a detener y determinar en qué líneas detenerse. Luego use el comando stop at para establecer un punto de interrupción en la línea del código fuente:

(dbx) file t.c

(dbx) list main

10 main( int argc, char *argv[])

11 {

12 char *msg = "hola mundo\n";

13 printit(msg);

14 }

(dbx) para en 13

(4) para en "t.c": 13

Para hacer el programa en el punto de interrupción Para detener y luego reanudar la ejecución, utilice el comando cont (consulte Reanudar la ejecución del programa y el comando cont).

Para obtener una lista de todos los puntos de interrupción actuales, utilice el comando de estado:

(dbx) status

(2) stop in main

(3) detenerse en "t.c": 13

Ahora, si ejecuta el programa, se detendrá en el primer punto de interrupción:

(dbx) ejecutar

detenido en main en la línea 12 del archivo "t.c"

12 char *msg = "hello world\n";

Programa de ejecución en un solo paso

El comando anterior se ejecuta hasta que la función actual devuelve el control a la función que lo llamó.

El comando step intenta ingresar a la función especificada en la línea de código fuente actual; si no se especifica ninguna función, intenta ingresar a la última función llamada determinada por el código ensamblador en la línea de código fuente actual. .

Algunas funciones (especialmente funciones de biblioteca como printf) pueden no compilarse con la opción -g, por lo que dbx no puede ingresar estas funciones. En este caso, el paso y el siguiente realizan funciones similares.

El siguiente ejemplo ilustra cómo utilizar los comandos paso y siguiente con puntos de interrupción establecidos en Establecer puntos de interrupción.

(dbx) para en 13

(3) para en "t.c": 13

(dbx) ejecuta

En ejecución: a.out

se detuvo en principal en la línea 13 del archivo "t.c"

13 printit(msg);

(dbx) next

Hola mundo

se detuvo en principal en la línea 14 del archivo "t.c"

14 }

(dbx) run

Ejecutando : a.out

se detuvo en principal en la línea 13 del archivo "t.c"

13 printit(msg);

(dbx) paso

se detuvo en printit en la línea 6 del archivo "t.c"

6 printf("s\n", msg);

(dbx) intensifica

Hola mundo

printit regresa

detenido en principal en la línea 13 del archivo "t.c"

13 printit (msg);

(dbx)

Para obtener más información sobre cómo ingresar a los programas, consulte Cómo ingresar a los programas. Para obtener más información sobre el comando de paso y el comando siguiente, consulte comando de paso y comando siguiente.

Ver la pila de llamadas

La pila de llamadas representa todas las rutinas que están actualmente activas, es decir, rutinas que han sido llamadas pero que aún no han regresado a sus respectivos llamadores. En esta pila, las funciones y sus argumentos se almacenan en el orden en que se llaman. Un seguimiento de la pila muestra en qué parte del flujo del programa se detuvo la ejecución y cómo llegó a ese punto. Proporciona la descripción más concisa del estado del programa.

Para mostrar un seguimiento de la pila, utilice el comando donde:

(dbx) stop in printf

(dbx) run

( dbx ) donde

[1] printf(0x10938, 0x20a84, 0x0, 0x0, 0x0, 0x0), en 0xef

=gt [2] printit(msg = 0x20a84 "hola; world \n"), línea 6 en "t.c"

[3]main(argc = 1, argv = 0xefffe93c), línea 13 en "t.c"

( dbx)

Para funciones compiladas con la opción -g, se conocen los nombres de los parámetros y sus tipos, por lo que se muestran los valores exactos. Para funciones sin información de depuración, los valores de los parámetros que se muestran son números hexadecimales. Estos números no siempre tienen sentido. Por ejemplo, en el seguimiento de la pila anterior, el fotograma 1 muestra el contenido de los registros de entrada SPARC $i0 a $i5, pero solo el contenido de los registros $i0 a $i1 es significativo porque se muestran en el programa ejecutable de un solo paso In. En el ejemplo, sólo se pasan dos parámetros a printf.

Se puede detener en una función compilada sin la opción -g.

Cuando se detiene en una función de este tipo, dbx busca en la pila el primer fotograma cuya función se compiló con la opción -g (printit() en este caso) y establece su alcance actual (consulte Alcance del programa). Esto está representado por el símbolo de flecha (=gt;).

Para obtener más información sobre la pila de llamadas, consulte Consideraciones de eficiencia.

Inspeccionar Variables

Aunque un seguimiento de pila puede contener suficiente información para mostrar completamente el estado del programa, aún es necesario ver los valores de otras variables. El siguiente ejemplo ilustra varias expresiones C simples:

(dbx) print msg

msg = 0x20a84 "Hola mundo"

(dbx) Print msg[0]

msg[0] = 'h'

(dbx) Imprimir *msg

*msg = 'h'

(dbx ) print msg

msg = 0xefffe8b4

Puede utilizar puntos de interrupción de cambio de datos para realizar un seguimiento de cuándo cambian los valores de variables y expresiones (consulte Configuración de puntos de interrupción de cambio de datos). Por ejemplo, para detener la ejecución cuando cambia el valor del recuento de la variable, escriba:

(dbx) detener el recuento de cambios

Busque problemas de acceso a la memoria y pérdidas de memoria

La verificación del tiempo de ejecución consta de dos partes: verificación del acceso a la memoria y verificación del uso de la memoria y verificación de fugas. Las comprobaciones de acceso comprueban si la aplicación que se está depurando utiliza la memoria de forma inadecuada. El uso de la memoria y la verificación de fugas implican rastrear todo el espacio de almacenamiento dinámico que aún existe, luego escanear el espacio de datos disponible e identificar el espacio no referenciado cuando sea necesario o cuando finalice el programa.

La verificación del acceso a la memoria y el uso de la memoria y la verificación de fugas se pueden habilitar usando el comando check. Para habilitar solo la verificación de acceso a la memoria, escriba:

(dbx) check -access

Para habilitar el uso de memoria y la verificación de pérdida de memoria, escriba:

( dbx) check -memuse

Ejecute el programa con los tipos de verificación de tiempo de ejecución requeridos habilitados. El programa funciona bien, pero es más lento porque hay una verificación de validez antes de cada acceso a la memoria. Si dbx detecta un acceso no válido, muestra el tipo y la ubicación del error. En este punto, puede usar comandos dbx (como el comando donde) para obtener el seguimiento de la pila actual, o usar el comando imprimir para examinar las variables.

Nota: La comprobación del tiempo de ejecución no se puede utilizar para aplicaciones que combinan código Java y código C JNI o ​​código C JNI.