2009-06-11 16 views
75

Me gustaría forzar un volcado del núcleo en una ubicación específica en mi aplicación C++.Cómo causar un volcado del núcleo en C/C++

sé que puedo hacerlo haciendo algo como:

int * crash = NULL; 
*crash = 1; 

Pero me gustaría saber si hay una manera más limpia?

Estoy usando Linux por cierto.

+15

A "más limpia" para volcar núcleo? .... buena persona;) –

+4

Esto es lindo. Mejor aún, use un booleano (¿enum en c?) ... if (* crash = TRUE) {/ * OH SHI ... * /} –

+3

Por cierto, ese método no funciona en todos los UNIX. HPUX, por ejemplo, le permite leer y escribir NULL con impunidad (afortunadamente, esto es configurable). – paxdiablo

Respuesta

64

elevación del número de señal 6 (SIGABRT en Linux) es una forma de hacerlo (aunque tenga en cuenta que SIGABRT no es requerido para ser 6 en todas las implementaciones POSIX, entonces puede querer usar el valor SIGABRT en sí mismo si esto no es más que quick'n 'código de depuración sucio'.

#include <signal.h> 
: : : 
raise (SIGABRT); 

Calling abort() también causará un volcado de memoria, e incluso se puede hacer esto sin la terminación de su proceso llamando fork() seguido por abort() en el niño - véase this answer para más detalles.

+7

No es necesario que SIGABRT sea la señal número 6 (aunque a menudo lo es, y específicamente, en Linux). –

+4

No, tienes razón, no es así, pero no me preocupo demasiado por la corrección del código de depuración. Si eso escapa a lo salvaje, la limpieza de mi código es la menor de mis preocupaciones :-) – paxdiablo

+2

Llamar a abort() puede ser inútil en algunas arquitecturas con algunos compiladores y algunas bibliotecas C (como gcc y glibc o uClibc en ARM) porque la función abort() se declara con un atributo __noreturn__ y el compilador optimiza totalmente toda la información de retorno, lo que hace que el archivo central no se pueda usar. No se puede rastrear más allá de la llamada para subir() o abortar(). Así que es mucho mejor llamar a raise (SIGABRT) directamente o kill (getpid(), SIGABRT), que es prácticamente lo mismo. –

30

Como se enumera en signal manpage, cualquier señal con la acción enumerada como 'núcleo' forzará un volcado del núcleo. Algunos ejemplos son:

SIGQUIT  3  Core Quit from keyboard 
SIGILL  4  Core Illegal Instruction 
SIGABRT  6  Core Abort signal from abort(3) 
SIGFPE  8  Core Floating point exception 
SIGSEGV  11  Core Invalid memory reference 

Asegúrese de que habilita núcleo vertederos:

ulimit -c unlimited 
+0

buen punto ~~~~~ –

+0

Gracias, su comentario sobre la habilitación de volcados núcleo con 'ulimit -c unlimited' ayudó. –

30
#include <stdlib.h> // C 
//#include <cstdlib> // C++ 

void core_dump(void) 
{ 
    abort(); 
} 
+1

¿Por qué no simplemente llamar 'abort()' directamente? – DepressedDaniel

4

Puede utilizar kill(2) para enviar la señal.

#include <sys/types.h> 
#include <signal.h> 
int kill(pid_t pid, int sig); 

Así,

kill(getpid(), SIGSEGV); 
+0

Entonces mata (getpid(), SIGxxx);? –

+0

Sí. Agregó eso a la respuesta. –

+2

SIGKILL no tira núcleo ... –

68

Hace unos años, Google lanzó la biblioteca coredumper.

general

La biblioteca coredumper se puede compilar en aplicaciones para crear volcados de memoria del programa en ejecución - sin necesidad de terminar. Admite volcados de núcleos de subprocesos múltiples y múltiples, incluso si el kernel no es compatible de forma nativa con los archivos principales de subprocesos múltiples.

Coredumper se distribuye bajo los términos de la licencia BSD.

Ejemplo

Esto de ninguna manera es un ejemplo completo; simplemente te da una idea de cómo es la API de coredumper.

#include <google/coredumper.h> 
... 
WriteCoreDump('core.myprogram'); 
/* Keep going, we generated a core file, 
* but we didn't crash. 
*/ 

No es lo que estaba pidiendo, pero tal vez es aún mejor :)

0
#include <assert.h> 
. 
. 
. 
    assert(!"this should not happen"); 
+0

Probablemente sea necesario que se bloquee con NDEBUG, por lo que esta afirmación en particular está activa incluso cuando otros aserciones no lo son. –

1

A veces puede ser apropiado hacer algo bajo la siguiente manera:

int st = 0; 
pid_t p = fork(); 

if (!p) { 
    signal(SIGABRT, SIG_DFL); 
    abort(); // having the coredump of the exact copy of the calling thread 
} else { 
    waitpid(p, &st, 0); // rip the zombie 
} 

// here the original process continues to live 

Uno El problema con este enfoque simple es que solo se fusionará un hilo.

3

Otra forma de generar un volcado de memoria:

$ bash 
$ kill -s SIGSEGV $$ 

acaba de crear una nueva instancia de la fiesta y matarlo con señal especificada. El $$ es el PID de el armazón. De lo contrario, estás matando a tu bash actual y se cerrará la sesión, la terminal se cerrará o desconectará.

$ bash 
$ kill -s SIGABRT $$ 
$ bash 
$ kill -s SIGFPE $$ 
+0

¡Muy simple y útil! – firo

+1

Me gusta ese, también. Incluso se puede simplificar a 'bash -c 'kill -SIGSEGV $$''. –

0
#include <stdio.h> 
#include <stdlib.h> 
int main() 
{ 
    printf("\n"); 
    printf("Process is aborting\n"); 
    abort(); 
    printf("Control not reaching here\n"); 
    return 0; 
} 

uso de este enfoque en la medida que desee :)

manera
Cuestiones relacionadas