2009-06-11 10 views
75

Ich möchte einen Core-Dump an einem bestimmten Speicherort in meiner C++ - Anwendung erzwingen.Wie programmgesteuert verursachen ein Core-Dump in C/C++

Ich weiß, dass ich es so, indem Sie etwas tun können:

int * crash = NULL; 
*crash = 1; 

Aber ich möchte wissen, ob es ein sauberer Weg?

ich Linux durch die Art und Weise verwenden.

+15

Ein "sauberer" Weg zum Core-Dumps? .... gut eins;) –

+4

Das ist süß. Besser noch eine boolean verwenden (enum in c?) ... Wenn (* crash = TRUE) {/ * OH SHI ... * /} –

+3

BTW, diese Methode funktioniert nicht in allen UNIXen. Mit HPUX können Sie zum Beispiel NULL ungestraft lesen und schreiben (zum Glück ist dies konfigurierbar). – paxdiablo

Antwort

64

Haltung von Signalnummer 6 (SIGABRT in Linux) ist eine Möglichkeit, dies zu tun (obwohl SIGABRT nicht erforderlich ist 6 in allen POSIX-Implementierungen, so dass Sie den Wert SIGABRT selbst verwenden möchten, wenn dies etwas anderes als Quick'n ist 'schmutziger Debug-Code).

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

Aufruf abort() auch einen Core Dump verursachen, und Sie können sogar diese ohne enden Ihren Prozess tun, indem fork() von abort() in dem Kind nur gefolgt Aufruf - this answer für Details.

+7

SIGABRT muss nicht Signal Nummer 6 sein (obwohl es oft ist - und ist insbesondere unter Linux). –

+4

Nein, Sie haben recht, es ist nicht, aber ich mache mir keine Sorgen über die Korrektheit des Debug-Codes. Wenn das in die Wildnis entkommt, ist die Sauberkeit meines Codes die geringste meiner Sorgen :-) – paxdiablo

+2

Calling abort() kann auf einigen Architekturen mit einigen Compilern und einigen C-Bibliotheken (wie gcc und glibc oder uClibc auf ARM) nutzlos sein, weil Die Funktion abort() wird mit einem Attribut __noreturn__ deklariert, und der Compiler optimiert alle Rückgabeinformationen vollständig, wodurch die Kerndatei unbrauchbar wird. Sie können es nicht nach dem Aufruf von raise() oder abort() selbst verfolgen. So ist es viel besser, raise (SIGABRT) direkt oder kill (getpid(), SIGABRT), was praktisch das Gleiche ist. –

30

Wie in der signal manpage aufgeführt, wird jedes Signal mit der als 'core' aufgeführten Aktion einen Core-Dump erzwingen. Einige Beispiele sind:

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 

Vergewissern Sie sich, dass Sie Kern ermöglichen Dumps:

ulimit -c unlimited 
+0

guten Punkt ~~~~~ –

+0

Danke, Ihre Bemerkung über das Aktivieren von Kern-Dumps mit 'ulimit -c unlimited' half. –

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

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

Warum nicht einfach 'abort()' direkt aufrufen? – DepressedDaniel

4

Sie kill(2) Signal zu senden, verwenden können.

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

So

kill(getpid(), SIGSEGV); 
+0

Also kill (getpid(), SIGxxx)? –

+0

Yup. Das zur Antwort hinzugefügt. –

+2

SIGKILL nicht Kern dumpen ... –

68

Vor einigen Jahren veröffentlichte Google die Bibliothek coredumper.

Übersicht

Die coredumper Bibliothek kann in Anwendungen erstellt werden, um Core-Dumps des laufenden Programms zu erstellen - ohne zu beenden. Es unterstützt sowohl Single- als auch Multi-Threaded-Core-Dumps, auch wenn der Kernel Multithread-Core-Dateien nicht nativ unterstützt.

Coredumper wird unter den Bedingungen der BSD-Lizenz vertrieben.

Beispiel

Dies ist keineswegs ein vollständiges Beispiel; es gibt Ihnen einfach ein Gefühl dafür, wie die Coredumper-API aussieht.

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

Es ist nicht das, was Sie fragen, aber vielleicht ist es besser, selbst :)

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

Wahrscheinlich muss man mit NDEBUG murren, damit diese bestimmte Assert auch dann aktiv ist, wenn andere Behauptungen nicht sind. –

1

Manchmal kann es sinnvoll sein, smth wie dies zu tun:

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 

One Problem mit diesem einfachen Ansatz ist, dass nur ein Thread coredumped wird.

3

Eine weitere Möglichkeit, ein Core-Dump der Erzeugung:

$ bash 
$ kill -s SIGSEGV $$ 

einfach eine neue Instanz der bash erstellen und es mit dem angegebenen Signal töten. Die $$ ist die PID der Shell. Andernfalls tötest du deine aktuelle Bash und wirst ausgeloggt, das Terminal geschlossen oder die Verbindung getrennt.

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

Sehr einfach und nützlich! – firo

+1

Ich mag das auch. Es kann sogar vereinfacht werden, '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; 
} 

Verwendung dieser Ansatz, wo immer Sie wollen :)