¿Cómo se determina dónde está el error en el código que causa una falla de segmentación ?
¿Puede mi compilador ( gcc
) mostrar la ubicación de la falla en el programa?
c++
c
debugging
segmentation-fault
Trilarion
fuente
fuente
Respuestas:
GCC no puede hacer eso, pero GDB (un depurador ) sí puede. Compile su programa usando el
-g
interruptor, así:Luego usa gdb:
Aquí hay un buen tutorial para comenzar con GDB.
El lugar donde se produce la falla predeterminada es generalmente solo una pista de dónde está "el error que causa" en el código. La ubicación dada no es necesariamente donde reside el problema.
fuente
bt
como una abreviatura debacktrace
.Además, puede
valgrind
intentarlo: si instalavalgrind
y ejecutaluego ejecutará su programa y mostrará los rastros de la pila para cualquier segfault, así como cualquier lectura o escritura de memoria no válida y pérdidas de memoria. Es realmente bastante útil.
fuente
--leak-check=full
no ayudará a depurar segfaults. Es útil solo para depurar fugas de memoria.También puede usar un volcado de núcleo y luego examinarlo con gdb. Para obtener información útil también necesita compilar con la
-g
bandera.Cada vez que recibes el mensaje:
se escribe un archivo central en su directorio actual. Y puedes examinarlo con el comando
El archivo contiene el estado de la memoria cuando el programa se bloqueó. Un volcado de núcleo puede ser útil durante la implementación de su software.
Asegúrese de que su sistema no establezca el tamaño del archivo de volcado del núcleo en cero. Puede establecerlo en ilimitado con:
ulimit -c unlimited
¡Pero cuidado! que los basureros pueden volverse enormes.
fuente
Hay varias herramientas disponibles que ayudan a depurar fallas de segmentación y me gustaría agregar mi herramienta favorita a la lista: Desinfectantes de direcciones (a menudo abreviado ASAN) .
Los compiladores modernos vienen con la práctica
-fsanitize=address
bandera, agregando algo de tiempo de compilación y tiempo de ejecución, lo que hace más verificación de errores.De acuerdo con la documentación, estas comprobaciones incluyen la detección de fallas de segmentación de forma predeterminada. La ventaja aquí es que obtiene un seguimiento de la pila similar a la salida de gdb, pero sin ejecutar el programa dentro de un depurador. Un ejemplo:
El resultado es un poco más complicado de lo que generaría gdb, pero hay ventajas:
No es necesario reproducir el problema para recibir un seguimiento de la pila. Simplemente habilitar la bandera durante el desarrollo es suficiente.
Los ASAN detectan mucho más que solo fallas de segmentación. Se capturarán muchos accesos fuera de límites incluso si esa área de memoria fuera accesible para el proceso.
¹ Eso es Clang 3.1+ y GCC 4.8+ .
fuente
La respuesta de Lucas sobre los vertederos es buena. En mi .cshrc tengo:
para mostrar la traza hacia atrás ingresando 'core'. Y el sello de fecha, para asegurarme de que estoy mirando el archivo correcto :(.
Agregado : si hay un error de corrupción de la pila , la traza inversa aplicada al volcado del núcleo a menudo es basura. En este caso, ejecutar el programa dentro de gdb puede dar mejores resultados, según la respuesta aceptada (suponiendo que la falla sea fácilmente reproducible). Y también tenga cuidado con los procesos múltiples que descargan el núcleo simultáneamente; algunos sistemas operativos agregan el PID al nombre del archivo central.
fuente
ulimit -c unlimited
habilitar los volcados de núcleo en primer lugar.Todas las respuestas anteriores son correctas y recomendadas; esta respuesta está destinada solo como último recurso si no se puede utilizar ninguno de los enfoques antes mencionados.
Si todo lo demás falla, siempre puede recompilar su programa con varias declaraciones temporales de impresión de depuración (por ejemplo
fprintf(stderr, "CHECKPOINT REACHED @ %s:%i\n", __FILE__, __LINE__);
) esparcidas a lo largo de lo que cree que son las partes relevantes de su código. Luego ejecute el programa y observe cuál fue la última impresión de depuración impresa justo antes de que ocurriera el bloqueo: sabe que su programa llegó tan lejos, por lo que el bloqueo debe haber sucedido después de ese punto. Agregue o elimine impresiones de depuración, vuelva a compilar y ejecute la prueba nuevamente, hasta que la haya reducido a una sola línea de código. En ese punto, puede corregir el error y eliminar todas las impresiones de depuración temporales.Es bastante tedioso, pero tiene la ventaja de funcionar en casi cualquier lugar: las únicas veces que podría no serlo es si no tiene acceso a stdout o stderr por alguna razón, o si el error que está tratando de solucionar es una carrera -condición cuyo comportamiento cambia cuando cambia el tiempo del programa (ya que las impresiones de depuración ralentizarán el programa y cambiarán su tiempo)
fuente