Chciałbym wymusić zrzut rdzenia w określonej lokalizacji w mojej aplikacji C ++.
Wiem, że mogę to zrobić, robiąc coś takiego:
int * crash = NULL;
*crash = 1;
Ale chciałbym wiedzieć, czy istnieje czystszy sposób?
Nawiasem mówiąc, używam Linuksa.
Chciałbym wymusić zrzut rdzenia w określonej lokalizacji w mojej aplikacji C ++.
Wiem, że mogę to zrobić, robiąc coś takiego:
int * crash = NULL;
*crash = 1;
Ale chciałbym wiedzieć, czy istnieje czystszy sposób?
Nawiasem mówiąc, używam Linuksa.
Odpowiedzi:
Podniesienie sygnału numer 6 ( SIGABRTw Linuksie) jest jednym ze sposobów na zrobienie tego (choć pamiętaj, że SIGABRT nie musi mieć 6 we wszystkich implementacjach POSIX, więc możesz chcieć użyć SIGABRTsamej wartości, jeśli jest to coś innego niż quick'n 'brudny kod debugowania).
#include <signal.h>
: : :
raise (SIGABRT);
Wywołanie abort()spowoduje również zrzutu pamięci, a można to zrobić nawet bez kończącego proces poprzez wywołanie fork()następuje abort()w dziecku tylko - zobacz tę odpowiedź szczegóły.
ulimit -c unlimitedudzielona przez Suvesh Pratapa, bardzo mi pomogła w uzyskaniu tej odpowiedzi.
Kilka lat temu firma Google udostępniła bibliotekę coredumper .
Przegląd
Bibliotekę coredumper można skompilować do aplikacji w celu tworzenia zrzutów jądra uruchomionego programu - bez przerywania pracy. Obsługuje zarówno jedno-, jak i wielowątkowe zrzuty rdzenia, nawet jeśli jądro nie obsługuje natywnie wielowątkowych plików rdzenia.
Coredumper jest rozpowszechniany na warunkach Licencji BSD.
Przykład
Nie jest to bynajmniej pełny przykład; po prostu daje ci poczucie, jak wygląda API coredumper.
#include <google/coredumper.h> ... WriteCoreDump('core.myprogram'); /* Keep going, we generated a core file, * but we didn't crash. */
Nie o to prosiłeś, ale może jest jeszcze lepiej :)
Jak podano na stronie podręcznika sygnału , każdy sygnał z akcją wymienioną jako „rdzeń” wymusi zrzut rdzenia. Oto kilka przykładów:
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
Upewnij się, że włączyłeś zrzuty podstawowe:
ulimit -c unlimited
setrlimit(RLIMIT_CORE, &core_limits);dostępnych przez #include <sys/resource.h>. Tworzysz strukturę typu, rlimita następnie ustawiasz elementy członkowskie rlim_curi rlim_max.
#include <stdlib.h> // C
//#include <cstdlib> // C++
void core_dump(void)
{
abort();
}
abort()bezpośrednio?
Odwołać się
abort();
Powiązane, czasami chciałbyś uzyskać śledzenie wstecz bez rzeczywistego zrzutu pamięci i pozwolić programowi na dalsze działanie: sprawdź funkcje glibc backtrace () i backtrace_symbols (): http://www.gnu.org/s/libc/ manual / html_node / Backtraces.html
Inny sposób generowania zrzutu pamięci:
$ bash
$ kill -s SIGSEGV $$
Po prostu utwórz nową instancję basha i zabij ją określonym sygnałem. To $$jest PID powłoki. W przeciwnym razie zabijesz swój obecny bash i zostaniesz wylogowany, terminal zamknięty lub odłączony.
$ bash
$ kill -s SIGABRT $$
$ bash
$ kill -s SIGFPE $$
bash -c 'kill -SIGSEGV $$'.
Możesz użyć kill (2) do wysłania sygnału.
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
Więc,
kill(getpid(), SIGSEGV);
Czasami warto zrobić coś takiego:
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
Jednym z problemów związanych z tym prostym podejściem jest to, że tylko jeden wątek zostanie poddany rdzeniu.
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("\n");
printf("Process is aborting\n");
abort();
printf("Control not reaching here\n");
return 0;
}
zastosuj to podejście gdziekolwiek chcesz :)
#include <assert.h>
.
.
.
assert(!"this should not happen");