Volcado de memoria, volcado de memoria, volcado de núcleo, volcado de sistema... todos producen el mismo resultado:un archivo que contiene el estado de la memoria de una aplicación en un momento específico, generalmente cuando la aplicación falla.
Saber cómo manejar estos archivos puede ayudarlo a encontrar la(s) causa(s) raíz(es) de una falla. Incluso si no es un desarrollador, los archivos de volcado creados en su sistema pueden ser muy útiles (así como accesibles) para comprender el software.
Este es un artículo práctico y puede seguir el ejemplo clonando el repositorio de la aplicación de muestra con:
git clone https://github.com/hANSIc99/core_dump_example.git
Cómo se relacionan las señales con los volcados
Más recursos de Linux
- Hoja de trucos de los comandos de Linux
- Hoja de trucos de comandos avanzados de Linux
- Curso en línea gratuito:Descripción general técnica de RHEL
- Hoja de trucos de red de Linux
- Hoja de trucos de SELinux
- Hoja de trucos de los comandos comunes de Linux
- ¿Qué son los contenedores de Linux?
- Nuestros últimos artículos sobre Linux
Las señales son un tipo de comunicación entre procesos entre el sistema operativo y las aplicaciones del usuario. Linux usa las señales definidas en el estándar POSIX. En su sistema, puede encontrar las señales estándar definidas en /usr/include/bits/signum-generic.h
. También hay una página de señales man informativa si desea obtener más información sobre el uso de señales en su aplicación. En pocas palabras, Linux usa señales para desencadenar más actividades en función de si se esperaban o no.
Cuando sale de una aplicación en ejecución, la aplicación generalmente recibirá el SIGTERM
señal. Debido a que se espera este tipo de señal de salida, esta acción no creará un volcado de memoria.
Las siguientes señales harán que se cree un archivo de volcado (fuente:GNU C Library):
- SIGFPE:Operación aritmética errónea
- SIGILL:Instrucción ilegal
- SIGSEGV:acceso no válido al almacenamiento
- SIGBUS:error de bus
- SIGABRT:Un error detectado por el programa y reportado llamando a abort
- SIGIOT:etiquetada como arcaica en Fedora, esta señal solía activarse en
abort()
en un PDP-11 y ahora se asigna a SIGABRT
Creación de archivos de volcado
Navegue hasta el core_dump_example
directorio, ejecute make
y ejecute la muestra con -c1
cambiar:
./coredump -c1
La aplicación debería salir en el estado 4 con un error:
"Abgebrochen (Speicherabzug geschrieben)" se traduce aproximadamente como "Error de segmentación (núcleo volcado)".
Si crea un volcado de núcleo o no, está determinado por el límite de recursos del usuario que ejecuta el proceso. Puede modificar los límites de recursos con el ulimit
comando.
Compruebe la configuración actual para la creación de volcados del núcleo:
ulimit -c
Si genera unlimited
, entonces está usando el valor predeterminado (recomendado). De lo contrario, corrija el límite con:
ulimit -c unlimited
Para deshabilitar la creación de tipos de volcados del núcleo:
ulimit -c 0
El número especifica el recurso en kilobytes.
¿Qué son los volcados de núcleo?
La forma en que el kernel maneja los volcados del núcleo se define en:
/proc/sys/kernel/core_pattern
Estoy ejecutando Fedora 31 y en mi sistema, el archivo contiene:
/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h
Esto muestra que los volcados del núcleo se reenvían a systemd-coredump
utilidad. El contenido de core_pattern
puede variar ampliamente entre los diferentes sabores de las distribuciones de Linux. Cuando systemd-coredump
está en uso, los archivos de volcado se guardan comprimidos en /var/lib/systemd/coredump
. No necesita tocar los archivos directamente; en su lugar, puede usar coredumpctl
. Por ejemplo:
coredumpctl list
muestra todos los archivos de volcado disponibles guardados en su sistema.
Con coredumpctl dump
, puede recuperar información del último archivo de volcado guardado:
[stephan@localhost core_dump_example]$ ./coredump
Application started…
(…….)
Message: Process 4598 (coredump) of user 1000 dumped core.
Stack trace of thread 4598:
#0 0x00007f4bbaf22625 __GI_raise (libc.so.6)
#1 0x00007f4bbaf0b8d9 __GI_abort (libc.so.6)
#2 0x00007f4bbaf664af __libc_message (libc.so.6)
#3 0x00007f4bbaf6da9c malloc_printerr (libc.so.6)
#4 0x00007f4bbaf6f49c _int_free (libc.so.6)
#5 0x000000000040120e n/a (/home/stephan/Dokumente/core_dump_example/coredump)
#6 0x00000000004013b1 n/a (/home/stephan/Dokumente/core_dump_example/coredump)
#7 0x00007f4bbaf0d1a3 __libc_start_main (libc.so.6)
#8 0x000000000040113e n/a (/home/stephan/Dokumente/core_dump_example/coredump)
Refusing to dump core to tty (use shell redirection or specify — output).
Esto muestra que el proceso fue detenido por SIGABRT
. El seguimiento de la pila en esta vista no es muy detallado porque no incluye nombres de funciones. Sin embargo, con coredumpctl debug
, simplemente puede abrir el archivo de volcado con un depurador (GDB por defecto). Escriba bt
(abreviatura de backtrace) para obtener una vista más detallada:
Core was generated by `./coredump -c1'.
Program terminated with signal SIGABRT, Aborted.
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50 return ret;
(gdb) bt
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x00007fc37a9aa8d9 in __GI_abort () at abort.c:79
#2 0x00007fc37aa054af in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7fc37ab14f4b "%s\n") at ../sysdeps/posix/libc_fatal.c:181
#3 0x00007fc37aa0ca9c in malloc_printerr (str=str@entry=0x7fc37ab130e0 "free(): invalid pointer") at malloc.c:5339
#4 0x00007fc37aa0e49c in _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:4173
#5 0x000000000040120e in freeSomething(void*) ()
#6 0x0000000000401401 in main ()
Las direcciones de memoria:main()
y freeSomething()
son bastante bajos en comparación con los fotogramas posteriores. Debido al hecho de que los objetos compartidos se asignan a un área al final del espacio de direcciones virtuales, puede suponer que SIGABRT
fue causado por una llamada en una biblioteca compartida. Las direcciones de memoria de los objetos compartidos no son constantes entre invocaciones, por lo que no hay ningún problema cuando ve direcciones variables entre llamadas.
El seguimiento de la pila muestra que las llamadas posteriores se originan en malloc.c
, lo que indica que algo con la (des)asignación de memoria podría haber salido mal.
En el código fuente, puede ver (incluso sin ningún conocimiento de C ++) que intentó liberar un puntero, que no fue devuelto por una función de administración de memoria. Esto da como resultado un comportamiento indefinido y hace que SIGABRT
:
void freeSomething(void *ptr){
free(ptr);
}
int nTmp = 5;
int *ptrNull = &nTmp;
freeSomething(ptrNull);
La utilidad systemd coredump se puede configurar en /etc/systemd/coredump.conf
. La rotación de la limpieza del archivo de volcado se puede configurar en /etc/systemd/system/systemd-tmpfiles-clean.timer
.
Puede encontrar más información sobre coredumpctl
en su página man.
Compilación con símbolos de depuración
Abra el Makefile
y comente la última parte de la línea 9. Ahora debería verse así:
CFLAGS =-Wall -Werror -std=c++11 -g
El -g
switch permite al compilador crear información de depuración. Inicie la aplicación, esta vez con -c2
cambiar:
./coredump -c2
Obtendrá una excepción de punto flotante. Abra el volcado en GDB con:
coredumpctl debug
Esta vez, se le dirige directamente a la línea del código fuente que provocó el error:
Reading symbols from /home/stephan/Dokumente/core_dump_example/coredump…
[New LWP 6218]
Core was generated by `./coredump -c2'.
Program terminated with signal SIGFPE, Arithmetic exception.
#0 0x0000000000401233 in zeroDivide () at main.cpp:29
29 nRes = 5 / nDivider;
(gdb)
Escribe list
para obtener una mejor visión general del código fuente:
(gdb) list
24 int zeroDivide(){
25 int nDivider = 5;
26 int nRes = 0;
27 while(nDivider > 0){
28 nDivider--;
29 nRes = 5 / nDivider;
30 }
31 return nRes;
32 }
Usa el comando info locals
para recuperar los valores de las variables locales desde el momento en que falló la aplicación:
(gdb) info locals
nDivider = 0
nRes = 5
En combinación con el código fuente, puede ver que se encontró con una división por cero:
nRes = 5 / 0
Conclusión
Saber cómo lidiar con los archivos de volcado lo ayudará a encontrar y corregir errores aleatorios difíciles de reproducir en una aplicación. Y si no es su aplicación, enviar un volcado del núcleo al desarrollador le ayudará a encontrar y solucionar el problema.