Как программно вызвать дамп ядра в C/C++

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

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

int * crash = NULL;
*crash = 1;

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

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

10 ответов

Решение

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

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

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

Несколько лет назад 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.
 */

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

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

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
#include <stdlib.h>   // C
//#include <cstdlib>  // C++

void core_dump(void)
{
    abort();
}

Прервать ();

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

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

$ bash
$ kill -s SIGSEGV $$

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

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

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

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

Так,

kill(getpid(), SIGSEGV);

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

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

Одна проблема с этим простым подходом состоит в том, что только один поток будет coredumped.

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

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

#include <assert.h>
.
.
.
     assert(!"this should not happen");
Другие вопросы по тегам