Как программно вызвать дамп ядра в 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;
}
используйте этот подход, где вы хотите:)