Red de conocimiento informático - Conocimiento del nombre de dominio - Cómo utilizar GDB para depurar archivos principales

Cómo utilizar GDB para depurar archivos principales

Esto suele deberse a un acceso fuera de límites a una matriz, un puntero nulo o una lectura o escritura comodín. Si el programa es pequeño, lo mejor es comprobar el código fuente repetidamente para solucionar el problema. Pero para programas con una gran cantidad de código, incluidas múltiples llamadas a funciones y múltiples accesos a punteros de matriz, no es fácil localizar el problema en este momento (en este momento, los vaqueros también pueden usar printf y búsqueda binaria en la ubicación correspondiente). localizar rápidamente :P). Si eres vago, simplemente usa GDB. Dios es el archivo Core Dump De vez en cuando escucho a amigos programadores quejarse "¡Maldita sea, Core ha vuelto a salir!". Los archivos de volcado de núcleo son simples. En pocas palabras, un volcado de núcleo es una operación realizada por el sistema operativo. Cuando un proceso finaliza inesperadamente (falla) por algún motivo, el sistema operativo vuelca la información de la memoria del proceso en el disco1. El archivo resultante es el archivo principal, generalmente llamado core.xxx. Cómo generar un volcado de núcleo Un volcado ocurre cuando un proceso recibe una señal, hay más de 60 señales en Linux, puede usar el comando kill -l para enumerarlas todas. sagi@sagi-laptop:~$ kill -l 1) SIGHUP 2)sigint 3) sigquit 4) sigill 5) sigtrap 6)sigabrt 7) sigbus 8) sigfpe 9) sigkill 10) sigusr1 11) sigsegv 12) sigusr2 13) sigpipe 14) sigalrm 15) sigterm 16) sigstkflt 17) sigchld 18)sigcont 19) sigstop 20) sigtstp 21) sigttin 22) sigttou 23) sigurg 24) sigxcpu 25) sigxfsz 26) sigvtalrm 27 ) sigprof 28) 29) sigio30) SIGPWR 31) Sigsys 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+742) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX Para una señal específica, el programa de aplicación puede escribir el programa de procesamiento de señal correspondiente y el programa de aplicación puede escribir la función de procesamiento de señal correspondiente. Si no se especifica, se procesará de forma predeterminada. El método de procesamiento predeterminado es coredump. La señal es la siguiente: 3) SIGQUIT 4) SIGILL 6) SIGABRT 8) SIGFPE 11) SIGSEGV 7) SIGBUS 31) SIGSYS 5) SIGTRAP 24) SIGXCPU 25) SIGXFSZ 29) SIGIOT Vemos SIGSEGV en señales mixtas, lo que generalmente ocurre cuando una matriz se sale de los límites o cuando se accede a un puntero nulo.

Además, aunque el valor predeterminado es este, también puede escribir su propia función de procesamiento de señales para cambiar el comportamiento predeterminado. Para obtener más información sobre las señales, consulte el enlace de referencia 33. El contenido anterior es solo una condición necesaria para generar coredump, pero no una condición suficiente. La generación de archivos principales también depende del shell en el que se ejecuta el programa. Puede usar el comando ulimit -a para ver el resultado. El resultado es aproximadamente el siguiente: sagi@sagi-laptop:~$ ulimit -a tamaño del archivo principal (. bloques, -c) 0 tamaño de segmento de datos (kbytes, -d) programación de prioridad ilimitada (-e) 20 tamaño de archivo (bloques, -f) señal pendiente ilimitada (-i) 16382 memoria máxima bloqueada (kbytes, -l) 64 máx tamaño de memoria (kbytes, -m) archivos abiertos ilimitados ( -n) 1024 tamaño de tubería (512 bytes. -p) 8 mensajes POSIX, -p) 8 cola de mensajes POSIX (bytes, -q) 819200 prioridad en tiempo real (-r ) 0 tamaño de pila (kilobytes, -s) 8192 Tiempo de CPU (segundos, -t) Procesos de usuario máximos ilimitados (-u) Memoria virtual ilimitada (kilobytes, -v) Bloqueos de archivos ilimitados (-x) Ilimitado ¿Ves esa primera línea? Tamaño del archivo principal, este valor se utiliza para limitar el tamaño del archivo principal generado; si excede este valor, no se guardará. Mi resultado aquí es 0, lo que significa que el archivo principal no se guardará, e incluso si se genera, no se guardará ==. Para cambiar esta configuración, use ulimit -c unlimited. Bien, ahora tenemos todo lo que necesitamos, excepto el programa para generar el kernel, que es demasiado simple para los programadores de C. #include ; #include ; int crash() { char *xxx = "crash!!!"; xxx[1] = 'D'; // Escribe almacenamiento de solo lectura } int foo() { return crash (); } int main() { return foo(); } Comenzando con la depuración El programa anterior debe compilarse con el parámetro -g para que el archivo ejecutable generado contenga suficiente información de depuración. Después de compilar y ejecutar el programa, debería ver el esperado "Error de segmento (núcleo volcado)" o "Error de segmento (núcleo volcado)". Busque el archivo core o core.xxx en el directorio actual. Usaremos el clásico depurador de Linux GDB para cargar un programa con un archivo principal: gdb exefile core. Cabe señalar que el archivo principal debe generarse mediante un archivo exe; de ​​lo contrario, la tabla de símbolos no coincidirá. El resultado después de la carga es el siguiente: sagi@sagi-laptop:~$ gdb coredump core El núcleo fue generado por ./coredump'. El programa finaliza con la señal 11, fallo de segmentación. #0 0x080483a7 en crash () en coredump.c:8 8 xxx[1] = 'D'; (gdb) Podemos ver que podemos encontrar directamente el kernel de salida y escribir una región de memoria de solo lectura en la línea 8, lo que provoca se activará una señal de fallo de segmentación. Hay un pequeño truco al cargar el kernel. Si no sabe de antemano qué programa generó el archivo del kernel, puede encontrar un reemplazo primero. Por ejemplo, /usr/bin/w es una buena opción.

Por ejemplo, si cargamos el núcleo generado anteriormente usando este método, gdb tendrá una salida similar a: sagi@sagi-laptop:~$ gdb /usr/bin/w core El núcleo fue generado por ./coredump'. El programa finaliza con la señal 11, fallo de segmentación. #0 0x080483a7 en ? () (gdb) Puede ver que GDB le ha preguntado qué programa generó este kernel. Operaciones comunes de GDB Los procedimientos anteriores son relativamente simples y no se requieren operaciones adicionales para detectar problemas. Pero esta no es la situación real. Por lo general, se requiere un seguimiento de un solo paso, el establecimiento de puntos de interrupción, etc., para localizar el problema con éxito. Algunas operaciones comunes del BGF se enumeran a continuación. Iniciar programa: ejecutar

Establecer punto de interrupción: b número de línea | nombre de función

Eliminar punto de interrupción: eliminar número de punto de interrupción

Deshabilitar punto de interrupción: deshabilitar número de punto de interrupción

Habilitar punto de interrupción: habilitar número de punto de interrupción

Seguimiento de un solo paso: siguiente también se puede abreviar como n

Seguimiento de un solo paso. el paso también se puede abreviar como s

Seguimiento de un solo paso: el paso también se puede abreviar como s

Imprimir variable: imprimir nombre de variable

Establecer variable: establecer var= valor

Ver tipo de variable: ptype var

Ejecutar secuencialmente hasta el final: cont

Ejecutar secuencialmente hasta una línea: util linenoImprime información de la pila: bt