[Depuración de código] Análisis de volcado de núcleos de Linux



1. Introducción

  En el artículo anterior, describí cómo usar la herramienta Valgrind para verificar problemas relacionados con la memoria, incluidas pérdidas de memoria, uso de puntero nulo, uso de puntero salvaje y liberación repetida. En la mayoría de los casos, la efectividad de Valgrind está más en la verificación de "pérdida de memoria", porque el acceso de punteros nulos y punteros salvajes provocará una falla de segmento (falla de segmento) y terminará. En este momento, puede usar el archivo coredump del sistema Linux. La combinación con la herramienta gdb puede localizar rápidamente la ubicación del problema. Además, hay muchas razones para que el sistema registre el archivo de volcado de núcleo causado por el bloqueo del programa. El acceso al puntero salvaje y al puntero nulo son solo uno de ellos. Por ejemplo, el desbordamiento de pila, la memoria fuera de límites, etc. causarán volcado de núcleo. Hacer un buen uso de los archivos de volcado de núcleo puede ayudarnos a resolver proyectos reales. El problema inusual.


2 volcado

2.1 ¿Qué es coredump?

   Coredump se refiere a cuando el programa de aplicación finaliza de forma anormal debido a varias razones, el sistema operativo registra la información de estado del programa de aplicación cuando la anomalía se produce como un archivo de coredump. Un archivo coredump contiene principalmente la información de la memoria, el estado del registro, la dirección de la pila y el contexto de llamada de función de la aplicación. El desarrollador analiza esta información para determinar la ubicación de la llamada cuando se produce la excepción del programa. Si se trata de un desbordamiento de la pila, es necesario analizar la función multicapa Información de llamada.

  En términos sencillos, coredump es el sistema operativo que registra la información de la terminación anormal de la aplicación, lo que nos deja la base para la resolución de problemas.


2.2 significado de coredump

  El papel de coredump para analizar las excepciones del programa es evidente. En el pasado, aprendimos MCU ARM de 32 bits como ejemplo (STM32). Debido al proceso de aprendizaje inicial, la calidad del código es desigual, lo que a menudo causa interrupciones por errores de hardware (Hard Fault). Ante esta situación, estamos indefensos. Por un lado, no hay información significativa registrada después de que ocurre el error del programa (por supuesto, la información de la pila se puede obtener en tiempo real a través del emulador, pero no es realista para el producto real); El problema es que la probabilidad de recurrencia es relativamente baja y las condiciones de recurrencia son inciertas. El sistema Linux es un sistema operativo "pensado", si el programa de aplicación es anormal, registrará alguna información clave, que es conveniente para nuestro análisis. Este es el significado de coredump.

  • Analizar la causa de la excepción del programa en función de la información registrada
  • Invertir las condiciones del problema según la información registrada y reproducir el problema para verificar

2.3 Escenarios generados por coredump

  Cuando ocurre una excepción en una aplicación, se generará un registro de archivo coredump. Estas excepciones están casi todas relacionadas con la memoria. En resumen, hay varios puntos.

[1] Acceso a la memoria fuera de límites

  • Subíndice de matriz fuera de límites
  • Fuera del alcance de la aplicación de memoria dinámica (malloc / nueva)
  • Las cadenas no tienen terminador y algunas funciones dependen del terminador de la cadena, como strcpy, strcmp, sprintf

[2] Acceder al puntero ilegal

  • Puntero nulo (memoria no solicitada)
  • Puntero salvaje (se ha liberado la memoria)
  • Suelte repetidamente el puntero (memoria)
  • Conversión forzada de puntero, la conversión forzada de puntero requiere un cuidado especial, lo que puede causar errores de acceso a la memoria debido a la alineación, la dirección de inicio y otros problemas

[3] Desbordamiento de pila, la asignación de una gran cantidad de variables locales, múltiples llamadas a funciones, recursividad profunda de funciones, etc. puede causar desbordamiento de pila

[4] Acceso multiproceso

  • Llamar a la función no reentrante
  • Los datos compartidos no son mutuamente excluyentes

2.2 Volcado de núcleo abierto

  De forma predeterminada, el sistema no habilita la función de grabación de volcado de núcleo, se ejecuta para "ulimit -c"verificar si está habilitada y devuelve 0 para indicar que la función de grabación de volcado de núcleo no está habilitada.

  • Compruebe si grabar coredump
acuity@ubuntu:~$ ulimit -c
1024

  Puede utilizar el “ulimit -c [size]”comando para especificar el tamaño del archivo de volcado de núcleo a grabar, es decir, para habilitar la grabación de volcado de núcleo. Cabe señalar que la unidad es 1 blockbloque = 512bytes.

  • Coredump abierto
acuity@ubuntu:~$ ulimit -c 1024

  ¿Qué sucede si el programa es incorrecto y el límite de tamaño de archivo de volcado de memoria especificado hace que falten o falten registros de archivo? En este momento, la solución de una vez por todas es no limitar el tamaño del archivo coredump; para ejecutar la “ulimit -c unlimited”configuración, se requieren privilegios de root para la configuración.

  • No hay límite en el tamaño del archivo de volcado de memoria
root@ubuntu:/home/acuity# ulimit -c unlimited
root@ubuntu:/home/acuity# ulimit -c 
unlimited

  Los métodos anteriores están todos configurados temporalmente para habilitar la función de grabación de volcado de memoria en el terminal, y se vuelve inválido después de que el sistema se reinicia Obviamente, este no es un método ideal. El método ideal es modificar el archivo de configuración para que el sistema siempre habilite la función de grabación coredump, al menos durante la fase de desarrollo y prueba del proyecto. En principio, el software también debe registrarse después de su lanzamiento, y puede haber una base para rastrear y analizar el problema después de que ocurra.

  • Habilitar mediante archivo de configuración

"/etc/profile"Agregado   en archivos " ulimit -c unlimited ".

Nota:

El comando ulimit es un comando para establecer límites de recursos. Además de coredump, también puede establecer otros límites de recursos

  • -a: Ver información de límite de recursos actual
  • -c <máximo del núcleo>: establece el valor máximo del archivo del núcleo, la unidad es bloque (bloque)
  • -d <tamaño del segmento de datos>: el valor máximo del segmento de datos de proceso, la unidad es KB
  • -f <tamaño de archivo>: el tamaño máximo de archivo que puede crear un proceso, en bloque
  • -H: establece el límite estricto de recursos, que no se puede cambiar después de configurar
  • -l <tamaño de la memoria>: tamaño de la memoria bloqueable, en KB
  • -m <tamaño de la memoria>: especifica el límite superior de memoria disponible, la unidad es KB
  • -n <número de archivos>: el número máximo de archivos que puede abrir el proceso (número de descriptores de archivo)
  • -p <tamaño del búfer>: el tamaño del búfer de la canalización, la unidad es KB
  • -s <tamaño de pila>: el tamaño máximo de pila de un hilo, en KB
  • -S: establece el límite elástico de recursos, que no puede exceder el límite de recursos físicos
  • -t <cpu time>: tiempo máximo de ocupación de la CPU, en segundos
  • -u <número de procesos>: el número máximo de procesos que el usuario puede crear
  • -v <tamaño de la memoria virtual>: la memoria virtual máxima disponible del proceso, en KB

  ** Además, coredump se puede activar configurando el código. ** Sin embargo, este método generalmente no se recomienda, porque si no hay una función de apertura agregada al código y la aplicación es anormal, el sistema no podrá grabar coredump. Se recomienda habilitarlo en la configuración del archivo de configuración del sistema.

Interfaz de acceso:

#include <sys/resource.h>

int getrlimit(int resource, struct rlimit *rlim);	/* 获取coredump 文件限制大
小 */
int setrlimit(int resource, const struct rlimit *rlim);/* 设置coredump 文件限制
大小 */
  • Función, obtener (establecer) el límite de recursos del sistema, coredump es solo un tipo de recurso del sistema, como el tamaño de la memoria virtual, la pila de procesos, el número máximo de procesos, etc.

  • resource, El identificador de recursos del sistema, para coredump, esRLIMIT_CORE

  • rlim, La estructura de datos de límite de recursos, que es el valor límite

    struct rlimit 
    {
          
            
    	rlim_t rlim_cur;  
    	rlim_t rlim_max;
    };
    
  • Devuelve 0 devuelve éxito, de lo contrario devuelve -1, el código de error almacenado en errorel

ejemplo:

#include <sys/resource.h>

int main(int argc, char * argv [ ])
{
    
    
	struct rlimit rlmt;
	
	rlmt.rlim_cur = (rlim_t)1024;
    rlmt.rlim_max  = (rlim_t)1024;

    if (-1 == setrlimit(RLIMIT_CORE, &rlmt)) 
    {
    
    
        perror("setrlimit error");
        return -1; 
    }   
}

2.3 ubicación de almacenamiento de volcado de núcleos y nombres

  El archivo coredump se almacena en el directorio de ejecución de la aplicación de forma predeterminada y el nombre del archivo es "core". Obviamente, usar el nombre de archivo predeterminado no es una buena manera. Si varias aplicaciones terminan de manera anormal, el archivo principal se sobrescribirá; o el demonio reiniciará y ejecutará la misma aplicación después de la terminación anormal, y el archivo principal se sobrescribirá cuando la excepción vuelva a ocurrir. .

  • Nombre de archivo con identificación de proceso (PID)

  Modifique el "/proc/sys/kernel/core_uses_pid"archivo, puede usar la identificación del proceso como extensión, el contenido del archivo es 1 para usar la extensión, el valor predeterminado es 0; cuando se usa la extensión de la identificación del proceso, el formato de archivo central generado es "core.xxx", xxx es la identificación del proceso.

  • Nombre y ubicación de almacenamiento más detallados

  La modificación del "/proc/sys/kernel/core_pattern"archivo puede establecer la ubicación de almacenamiento del archivo coredump y un nombre de archivo más detallado. La ubicación predeterminada y la información del nombre es la siguiente:

root@ubuntu:/home/acuity# cat /proc/sys/kernel/core_pattern
|/usr/share/apport/apport %p %s %c %d %P %E

  Significado de los caracteres extendidos:

%p - 扩展进程id(pid)
%P - 与%p作用相同
%u - 扩展用户id(uid)
%g - 扩展组id(gid)
%s - 扩展产生信号
%t - 扩展当前时间,从1970-01-0100:00:00开始的秒数
%h - 扩展主机名
%e - 扩展应用程序文件名称
%E - 扩展应用程序文件名称,包括文件绝对路径

  El directorio de almacenamiento de coredump permanece sin cambios (almacenado en el directorio de la aplicación actual) y el nombre de la extensión del archivo se incrementa con el nombre del archivo de la aplicación, el ID del proceso y la hora actual. Este es el uso básico que se usa comúnmente en escenarios reales. Se puede aplicar en ocasiones absolutamente determinadas. Puede usar vi para abrir directamente el archivo para editarlo, o puede usarlo para echomodificar el contenido del archivo, siempre que deba modificarlo con privilegios de root.

  • Genera “core.name.pit.time”archivos en el directorio actual de la aplicación.
echo ./core.%e.%p.%t > /proc/sys/kernel/core_pattern

  Si necesita especificar otra ruta de almacenamiento, puede modificar la parte de la ruta.

  • “/home”Genera “core-name-pit-time”archivos en el directorio
echo /home/core-%e-%p-%t > /proc/sys/kernel/core_pattern

Nota:

Si especifica ciertos directorios, puede generar un archivo coredump, pero el contenido del archivo está vacío. ¿Quizás es un problema de permisos? ?


3 Utilice coredump

  Escriba un programa "ilegal", deje que el sistema registre el volcado de memoria y analice el proceso con gdb; es necesario agregarlo durante la compilación para "-g"conservar la información de depuración.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char * argv [ ])
{
    
    	
	int *p = NULL;

	p = malloc(4);
	if (p == NULL)
	{
    
    
		perror("malloc failed");
	}
    printf("address [0x%p]\r\n", p);
	
	free(p);	
	free(p);	/* 重复释放*/
	
    return 0;
}

  Compile y ejecute el programa, y ​​el programa se cerrará de forma anormal debido al acceso al puntero salvaje, y se generará un archivo coredump.

  • Ver archivo coredump
root@ubuntu:/usr# file core.coredump.2046.1591860958 
core.coredump.2046.1591860958: ELF 64-bit LSB core file x86-64, version 1 (SYSV), SVR4-style, from './coredump'

Nota:

A veces, coredump solo genera un archivo vacío, que se puede ver a través del comando "archivo"

  • Iniciar el comando de depuración de gdb
gdb exe-file core-file

  • Ver información de coredump
gdb后,键入“bt”

  • Resultados de la

Inserte la descripción de la imagen aquí

  A través del análisis, la anomalía se encuentra en la línea 17. Mirando a través del código fuente, la línea 17 realizó la operación de liberar repetidamente la aplicación de memoria dinámica.


4 Artículos de referencia

[1] Volcado de núcleo detallado

[2] Formación y análisis de archivos Core Dump en Linux

[3] Una discusión provocada por coreDump

Supongo que te gusta

Origin blog.csdn.net/qq_20553613/article/details/106672319
Recomendado
Clasificación