Как программно вызвать дамп ядра в C / C ++ - PullRequest
81 голосов
/ 11 июня 2009

Я бы хотел принудительно создать дамп ядра в определенном месте в моем приложении C ++.

Я знаю, что могу сделать что-то вроде:

int * crash = NULL;
*crash = 1;

Но я хотел бы знать, есть ли более чистый путь?

Кстати, я использую Linux.

Ответы [ 10 ]

70 голосов
/ 11 июня 2009

Несколько лет назад Google выпустил библиотеку coredumper .

Обзор

Библиотека coredumper может быть скомпилирована в приложения для создания дампов ядра работающей программы - без прерывания. Он поддерживает как однопоточные, так и многопоточные дампы ядра, даже если ядро ​​не поддерживает многопоточные файлы ядра.

Coredumper распространяется на условиях лицензии BSD.

Пример

Это далеко не полный пример; это просто дает вам представление о том, как выглядит API coredumper.

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

Это не то, что вы просили, но, может быть, это даже лучше :)

66 голосов
/ 11 июня 2009

Повышение сигнала номер 6 (SIGABRT в Linux) является одним из способов сделать это (хотя имейте в виду, что SIGABRT не требуется , чтобы быть 6 во всех реализациях POSIX, поэтому вы можете использовать само значение SIGABRT, если это не что иное, как код отладки quick'n'dirty).

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

Вызов abort() также вызовет дамп ядра, и вы даже можете сделать это без завершения вашего процесса, вызвав fork(), за которым следует abort() только для дочернего процесса - см. ответ для деталей.

34 голосов
/ 11 июня 2009

Как указано в справочной странице сигнала , любой сигнал с действием, указанным как «ядро», вызовет дамп ядра. Вот некоторые примеры:

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

Убедитесь, что вы включили дампы ядра:

ulimit -c unlimited
30 голосов
/ 11 июня 2009
#include <stdlib.h>   // C
//#include <cstdlib>  // C++

void core_dump(void)
{
    abort();
}
11 голосов
/ 11 июня 2009

преждевременное прекращение ();

В связи с этим иногда требуется обратная трассировка без реального дампа памяти и разрешение программе продолжить работу: проверьте функции glibc backtrace () и backtrace_symbols (): http://www.gnu.org/s/libc/manual/html_node/Backtraces.html

5 голосов
/ 03 июля 2013

Другой способ создания дампа ядра:

$ bash
$ kill -s SIGSEGV $$

Просто создайте новый экземпляр bash и уничтожьте его указанным сигналом. $$ - это PID оболочка В противном случае вы убиваете свой текущий bash и выйдете из системы, терминал будет закрыт или отключен.

$ bash 
$ kill -s SIGABRT $$
$ bash
$ kill -s SIGFPE $$
4 голосов
/ 11 июня 2009

Вы можете использовать kill (2) для отправки сигнала.

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

Итак,

kill(getpid(), SIGSEGV);
2 голосов
/ 14 августа 2012

Иногда может быть уместно сделать что-то вроде этого:

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

Одна из проблем этого простого подхода заключается в том, что только один поток будет подвергнут coredump.

1 голос
/ 29 октября 2013
 #include <stdio.h>
 #include <stdlib.h>
 int main()
 {
   printf("\n");
   printf("Process is aborting\n");
   abort();
   printf("Control not reaching here\n");
   return 0;
 }

используйте этот подход, где хотите :)

0 голосов
/ 11 июня 2009
#include <assert.h>
.
.
.
     assert(!"this should not happen");
...