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?
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
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
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.
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 .
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 .
$ 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?
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
.
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:
-
W
/etc/profile
skomentuj wiersz:# ulimit -S -c 0 > /dev/null 2>&1
-
W
/etc/security/limits.conf
skomentuj wiersz:* soft core 0
-
Uruchom cmd
limit coredumpsize unlimited
i sprawdź go za pomocą cmdlimit
:# 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 #
-
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.) !
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
-
Sprawdzanie włączonego zrzutu pamięci:
ulimit -a
-
Jedna z linijek powinna brzmieć:
core file size (blocks, -c) unlimited
-
Jeśli nie:
gedit ~/.bashrc
i dodajulimit -c unlimited
do końca pliku i zapisz, uruchom ponownie terminal. -
Zbuduj swoją aplikację z informacjami o debugowaniu:
In Makefile
-O0 -g
-
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
-
Uruchom pod gdb:
gdb application_name core
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.
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));
}
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