Jak wygenerować zrzut pamięci w Linuksie, gdy proces dostaje błąd segmentacji?

Mam proces w Linuksie, który dostaje błąd segmentacji. Jak mogę powiedzieć, że generuje zrzut pamięci, gdy się nie powiedzie?

Author: Mark Harrison, 2008-08-20

10 answers

To zależy od tego, jakiej powłoki używasz. Jeśli używasz bash, to polecenie ulimit kontroluje kilka ustawień związanych z wykonywaniem programu, takich jak to, czy należy zrzucać rdzeń. Jeśli wpiszesz

ulimit -c unlimited

To powie bashowi, że jego programy mogą zrzucać rdzenie o dowolnej wielkości. Możesz określić rozmiar taki jak 52m zamiast nieograniczony, jeśli chcesz, ale w praktyce nie powinno to być konieczne, ponieważ rozmiar plików core prawdopodobnie nigdy nie będzie dla Ciebie problemem.

W tcsh, typujesz

limit coredumpsize unlimited
 216
Author: Eli Courtwright,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-17 22:22:13

Jak wyjaśniono powyżej, prawdziwym pytaniem jest, jak włączyć zrzuty pamięci w systemie, w którym nie są włączone. Odpowiedź na to pytanie znajduje się tutaj.

Jeśli przyszedłeś tutaj z nadzieją, aby dowiedzieć się, jak wygenerować zrzut pamięci dla procesu zawieszonego, odpowiedź brzmi

gcore <pid>

Jeśli gcore nie jest dostępny w Twoim systemie to

kill -ABRT <pid>

Nie używaj kill-SEGV, ponieważ często będzie wywoływać obsługę sygnału, co utrudnia diagnozowanie zablokowanego procesu

 46
Author: George Colpitts,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-22 20:51:05

To co zrobiłem na końcu to podłączenie gdb do procesu przed jego awarią, a potem kiedy dostał segfault wykonałem generate-core-file polecenie. To wymuszone generowanie zrzutu rdzenia.

 22
Author: Nathan Fellman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-26 13:33:27

Może mógłbyś to zrobić w ten sposób, ten program jest demonstracją jak pułapka błąd segmentacji i powłoki do debuggera (jest to oryginalny kod używany w AIX) i drukuje ślad stosu aż do punktu błędu segmentacji. Będziesz musiał zmienić zmienną sprintf na gdb W przypadku Linuksa.

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <stdarg.h>

static void signal_handler(int);
static void dumpstack(void);
static void cleanup(void);
void init_signals(void);
void panic(const char *, ...);

struct sigaction sigact;
char *progname;

int main(int argc, char **argv) {
    char *s;
    progname = *(argv);
    atexit(cleanup);
    init_signals();
    printf("About to seg fault by assigning zero to *s\n");
    *s = 0;
    sigemptyset(&sigact.sa_mask);
    return 0;
}

void init_signals(void) {
    sigact.sa_handler = signal_handler;
    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = 0;
    sigaction(SIGINT, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGSEGV);
    sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGBUS);
    sigaction(SIGBUS, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGQUIT);
    sigaction(SIGQUIT, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGHUP);
    sigaction(SIGHUP, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGKILL);
    sigaction(SIGKILL, &sigact, (struct sigaction *)NULL);
}

static void signal_handler(int sig) {
    if (sig == SIGHUP) panic("FATAL: Program hanged up\n");
    if (sig == SIGSEGV || sig == SIGBUS){
        dumpstack();
        panic("FATAL: %s Fault. Logged StackTrace\n", (sig == SIGSEGV) ? "Segmentation" : ((sig == SIGBUS) ? "Bus" : "Unknown"));
    }
    if (sig == SIGQUIT) panic("QUIT signal ended program\n");
    if (sig == SIGKILL) panic("KILL signal ended program\n");
    if (sig == SIGINT) ;
}

void panic(const char *fmt, ...) {
    char buf[50];
    va_list argptr;
    va_start(argptr, fmt);
    vsprintf(buf, fmt, argptr);
    va_end(argptr);
    fprintf(stderr, buf);
    exit(-1);
}

static void dumpstack(void) {
    /* Got this routine from http://www.whitefang.com/unix/faq_toc.html
    ** Section 6.5. Modified to redirect to file to prevent clutter
    */
    /* This needs to be changed... */
    char dbx[160];

    sprintf(dbx, "echo 'where\ndetach' | dbx -a %d > %s.dump", getpid(), progname);
    /* Change the dbx to gdb */

    system(dbx);
    return;
}

void cleanup(void) {
    sigemptyset(&sigact.sa_mask);
    /* Do any cleaning up chores here */
}

Być może będziesz musiał dodatkowo dodać parametr, aby gdb zrzuciło rdzeń, jak pokazano na tym blogu tutaj .

 19
Author: t0mm13b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-19 06:50:41

Aby sprawdzić, gdzie są generowane zrzuty rdzenia, Uruchom:

sysctl kernel.core_pattern

Gdzie %e jest nazwą procesu i %t czasem systemowym. Możesz go zmienić w /etc/sysctl.conf i przeładować przez sysctl -p.

Jeśli pliki core nie są generowane (przetestuj je przez: sleep 10 & i killall -SIGSEGV sleep), sprawdź limity przez: ulimit -a.

Jeśli Rozmiar pliku core jest ograniczony, Uruchom:

ulimit -c unlimited

Aby było nieograniczone.

Następnie przetestuj ponownie, jeśli dumping rdzenia się powiedzie, zobaczysz "(core dumping)" po Wskazanie błędu segmentacji jak poniżej:

Błąd segmentacji: 11 (Core)


Ubuntu

W Ubuntu Zwykle zrzuty są obsługiwane przez apport w /var/crash/, ale w innym formacie, jednak nie jest domyślnie włączone w stabilnych wydaniach. Czytaj więcej na Ubuntu wiki .

W przeciwieństwie do innych programów, nie można ich używać.]}
$ cat /proc/sys/kernel/core_pattern
|/usr/share/apport/apport %p %s %c

Więc nawet pliki core są wyłączone przez ulimit, apport będzie nadal uchwycić crash (Jak włączyć lub wyłączyć Apport?).


MacOS

Dla macOS, zobacz: jak generować zrzuty pamięci w Mac OS X?

 17
Author: kenorb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-19 00:40:26

Jest więcej rzeczy, które mogą mieć wpływ na generowanie zrzutu pamięci. Natknąłem się na te:

  • katalog dla zrzutu musi być zapisywalny. Domyślnie jest to bieżący katalog procesu, ale może zostać zmieniony przez ustawienie /proc/sys/kernel/core_pattern.
  • w pewnych warunkach wartość jądra w {[1] } może uniemożliwić wygenerowanie rdzenia.

Jest więcej sytuacji, które mogą uniemożliwić generowanie, które są opisane na stronie podręcznika-try man core.

 15
Author: mlutescu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-08 10:31:21

Aby aktywować zrzut pamięci wykonaj następujące czynności:

  1. W /etc/profile skomentuj wiersz:

    # ulimit -S -c 0 > /dev/null 2>&1
    
  2. W /etc/security/limits.conf skomentuj wiersz:

    *               soft    core            0
    
  3. Uruchom cmd limit coredumpsize unlimited i sprawdź go za pomocą cmd limit:

    # limit coredumpsize unlimited
    # limit
    cputime      unlimited
    filesize     unlimited
    datasize     unlimited
    stacksize    10240 kbytes
    coredumpsize unlimited
    memoryuse    unlimited
    vmemoryuse   unlimited
    descriptors  1024
    memorylocked 32 kbytes
    maxproc      528383
    #
    
  4. Aby sprawdzić, czy plik corefile zostanie napisany, możesz zabić powiązany proces za pomocą cmd kill -s SEGV <PID> (nie powinno być potrzebne, tylko w przypadku, gdy żaden plik core nie zostanie napisany, może to być użyte jako "check": {]}

    # kill -s SEGV <PID>
    

Po napisaniu pliku corefile należy ponownie dezaktywować ustawienia zrzutu coredump w powiązanych plikach (1 ./2./3.) !

 8
Author: Edgar Jordi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-05 17:29:47

Dla Ubuntu 14.04

  1. Sprawdzanie włączonego zrzutu pamięci:

    ulimit -a
    
  2. Jedna z linijek powinna brzmieć:

    core file size          (blocks, -c) unlimited
    
  3. Jeśli nie:

    gedit ~/.bashrc i dodaj ulimit -c unlimited do końca pliku i zapisz, uruchom ponownie terminal.

  4. Zbuduj swoją aplikację z informacjami o debugowaniu:

    In Makefile -O0 -g

  5. Uruchom aplikację, która utworzy zrzut pamięci (plik zrzutu pamięci o nazwie 'core' powinien zostać utworzony w pobliżu nazwy aplikacji plik):

    ./application_name
    
  6. Uruchom pod gdb:

    gdb application_name core
    
 7
Author: mrgloom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-25 17:17:30

Domyślnie otrzymasz plik core. Sprawdź, czy bieżący katalog procesu jest zapisywalny lub nie zostanie utworzony żaden plik core.

 4
Author: Mark Harrison,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-20 14:38:36

Lepiej włączyć programowo zrzut pamięci za pomocą wywołania systemowego setrlimit.

Przykład:

#include <sys/resource.h>

bool enable_core_dump(){    
    struct rlimit corelim;

    corelim.rlim_cur = RLIM_INFINITY;
    corelim.rlim_max = RLIM_INFINITY;

    return (0 == setrlimit(RLIMIT_CORE, &corelim));
}
 0
Author: kgbook,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-24 08:52:59