Come provocare programmaticamente un core dump in C / C ++


93

Vorrei forzare un core dump in una posizione specifica nella mia applicazione C ++.

So che posso farlo facendo qualcosa come:

int * crash = NULL;
*crash = 1;

Ma vorrei sapere se esiste un modo più pulito?

Sto usando Linux, comunque.


18
Un modo "più pulito" per il core dump? .... buona;)
GU.

5
Questo è carino. Meglio ancora usare un booleano (enum in c?) ... if ( crash = TRUE) {/ OH SHI ... * /}
Ape-inago,

3
BTW, quel metodo non funziona in tutti gli UNIX. HPUX, per esempio, ti consente di leggere e scrivere NULL impunemente (per fortuna, questo è configurabile).
paxdiablo

1
Ho appena imparato 3 o 4 grandi cose nuove. Grazie.
Trevor Boyd Smith,

@pax questo è più un motivo per trovare un modo generico;) Grazie
hhafez,

Risposte:


76

L'aumento del segnale numero 6 ( SIGABRTin Linux) è un modo per farlo (anche se tieni presente che SIGABRT non deve essere 6 in tutte le implementazioni POSIX quindi potresti voler usare il SIGABRTvalore stesso se questo è qualcosa di diverso da quick'n 'codice di debug sporco).

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

La chiamata abort()causerà anche un core dump, e puoi anche farlo senza terminare il processo chiamando fork()seguito da solo abort()nel bambino - vedi questa risposta per i dettagli.


7
SIGABRT non deve essere il segnale numero 6 (sebbene spesso lo sia - ed è, specificamente, su Linux).
Jonathan Leffler,

4
No, hai ragione, non lo è, ma tendo a non preoccuparmi troppo della correttezza del codice di debug. Se questo scappa in natura, la pulizia del mio codice è l'ultima delle mie preoccupazioni :-)
paxdiablo

2
Chiamare abort () può essere inutile su alcune architetture con alcuni compilatori e alcune librerie C (come gcc e glibc o uClibc su ARM) perché la funzione abort () è dichiarata con un attributo noreturn e il compilatore ottimizza totalmente tutte le informazioni di ritorno, il che rende inutilizzabile il file core. Non puoi rintracciarlo oltre la chiamata a raise () o abort () stesso. Quindi è molto meglio chiamare raise (SIGABRT) direttamente o kill (getpid (), SIGABRT), che è praticamente lo stesso.
Alexander Amelkin

3
Spiacenti, su ARM la stessa cosa accade anche con rilancio (SIGABRT). Quindi l'unico modo per produrre un file core tracciabile è kill (getpid (), SIGABRT)
Alexander Amelkin

Il suggerimento ulimit -c unlimiteddella risposta di Suvesh Pratapa mi ha aiutato molto per questa risposta.
Boris Däppen

74

Alcuni anni fa, Google ha rilasciato la libreria coredumper .

Panoramica

La libreria coredumper può essere compilata in applicazioni per creare core dump del programma in esecuzione, senza terminare. Supporta core dump sia single che multi-thread, anche se il kernel non supporta nativamente i core file multi-thread.

Coredumper è distribuito secondo i termini della licenza BSD.

Esempio

Questo non è affatto un esempio completo; ti dà semplicemente un'idea di come appare l'API coredumper.

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

Non è quello che stavi chiedendo, ma forse è anche meglio :)


3
Inizialmente ero piuttosto eccitato quando mi sono imbattuto in questa risposta. Ma il core dumper sembra piuttosto vecchio e decrepito in questi giorni. C'è anche l'indicazione che non funziona più su Linux kernel contemporanea: stackoverflow.com/questions/38314020/...
jefe2000

37

Come elencato nella manpage del segnale , qualsiasi segnale con l'azione elencata come 'core' forzerà un core dump. Alcuni esempi sono:

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

Assicurati di abilitare i core dump:

ulimit -c unlimited

Grazie, la tua osservazione sull'abilitazione dei core dump con ulimit -c unlimitedaiuto.

Come impostereste l'ulimit dall'interno del codice? @ ks1322
Karan Joisher,

@KaranJoisher Questo probabilmente vale un'altra domanda a sé stante, ma in breve puoi usare setrlimit(RLIMIT_CORE, &core_limits);disponibile tramite #include <sys/resource.h>. Si crea una struttura di tipo rlimite quindi si impostano i membri rlim_cure rlim_max.
Brent scrive il codice

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

void core_dump(void)
{
    abort();
}

3
Perché non chiamare abort()direttamente?
Depressed


6

Un altro modo per generare un core dump:

$ bash
$ kill -s SIGSEGV $$

Basta creare una nuova istanza di bash e ucciderla con il segnale specificato. Il $$è il PID della shell. Altrimenti stai uccidendo il tuo attuale bash e verrai disconnesso, il terminale chiuso o disconnesso.

$ bash 
$ kill -s SIGABRT $$
$ bash
$ kill -s SIGFPE $$

Molto semplice e utile!
firo

1
Anche quello mi piace. Può anche essere semplificato bash -c 'kill -SIGSEGV $$'.
Christian Krause

4

Puoi usare kill (2) per inviare il segnale.

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

Così,

kill(getpid(), SIGSEGV);

Sì. Aggiunto quello alla risposta.
Eugene Yokota,

2

A volte può essere appropriato fare qualcosa del genere:

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

Un problema con questo semplice approccio è che solo un thread verrà sottoposto a coreump.


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

usa questo approccio ovunque tu voglia :)


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

Probabilmente è necessario fare il muck con NDEBUG quindi questa particolare asserzione è attiva anche quando altre asserzioni non lo sono.
Rhys Ulerich
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.