Linux에서 세그멘테이션 오류로 코어 덤프를 생성하는 방법은 무엇입니까?


답변:


249

사용중인 쉘에 따라 다릅니다. bash를 사용하는 경우 ulimit 명령은 코어 실행 여부와 같은 프로그램 실행과 관련된 여러 설정을 제어합니다. 입력하면

ulimit -c unlimited

그러면 프로그램이 어떤 크기의 코어도 덤프 할 수 있다고 bash에 알릴 것입니다. 원하는 경우 무제한 대신 52M과 같은 크기를 지정할 수 있지만 실제로는 코어 파일의 크기가 결코 문제가되지 않으므로 필요하지 않습니다.

tcsh에서는 다음을 입력합니다

limit coredumpsize unlimited

21
@lzprgmr : 명확히하기 위해 : 기본적으로 코어 덤프가 생성되지 않는 이유는 한계가 설정되지 않았거나 0으로 설정되어 코어가 덤프되지 않기 때문입니다. 제한을 무제한으로 설정하면 코어 덤프를 항상 생성 할 수 있습니다.
— Eli Courtwright

6
이 링크 는 더 깊이 들어가고 리눅스에서 코어 덤프 생성을 가능하게하는 더 많은 옵션을 제공합니다. 유일한 단점은 일부 명령 / 설정이 설명 할 수 없다는 것입니다.
— 살사

6
bash 4.1.2 (1)에서 52M과 같은 릴리스 제한을 지정할 수 없으므로 잘못된 숫자 오류 메시지가 나타납니다. 매뉴얼 페이지에는 "값이 1024 바이트 단위로 증가합니다"라고 알려줍니다.
— a1an

4
글쎄, "작은"OpenGL 프로젝트가 있었는데, 한때 이상한 일을했고 X 서버 충돌을 일으켰습니다. 다시 로그인하면 귀여운 17GB 코어 파일 (25GB 파티션)을 보았습니다. 핵심 파일의 크기를 제한적으로 유지하는 것이 좋습니다 :)
— IceCool

1
@PolarisUser : 파티션을 먹지 않으려면 1 공연과 같은 한도를 설정하는 것이 좋습니다. 남은 하드 드라이브 공간을 모두 사용하겠다고 위협하지 않으면 서 합리적인 코어 덤프를 처리 할 수있을만큼 커야합니다.
— Eli Courtwright

60

위에서 설명한 것처럼 여기서 실제로 묻는 질문은 활성화되지 않은 시스템에서 코어 덤프를 활성화하는 방법입니다. 그 질문에 대한 답이 여기에 있습니다.

중단 된 프로세스에 대한 코어 덤프를 생성하는 방법을 배우려고 여기에 온다면 그 대답은

gcore <pid>

시스템에서 gcore를 사용할 수없는 경우

kill -ABRT <pid>

kill -SEGV를 사용하지 마십시오. 종종 신호 처리기를 호출하여 걸린 프로세스를 진단하기 어렵게 만듭니다.


나는 그것이 훨씬 더 가능성이 그 생각 -ABRT보다 신호 처리기를 호출합니다 -SEGV중지 판단이 segfault의 이상 복구 할 가능성이 더 높습니다로. segfault를 처리하는 경우 일반적으로 처리기가 종료 되 자마자 다시 트리거됩니다. 코어 덤프 생성을위한 더 나은 신호 선택은입니다 -QUIT.
— celticminstrel

32

코어 덤프가 생성되는 위치를 확인하려면 다음을 실행하십시오.

sysctl kernel.core_pattern

또는:

cat /proc/sys/kernel/core_pattern

%e프로세스 이름과 %t시스템 시간 은 어디에 있습니까 ? 에서 변경 /etc/sysctl.conf하고 다시로드 할 수 있습니다 sysctl -p.

코어 파일이 생성되지 않은 경우 ( sleep 10 &및로 테스트 killall -SIGSEGV sleep) 다음으로 한계를 확인하십시오 ulimit -a.

코어 파일 크기가 제한되어 있으면 다음을 실행하십시오.

ulimit -c unlimited

무제한으로 만들 수 있습니다.

그런 다음 코어 덤핑에 성공하면 다음과 같이 세그먼테이션 오류 표시 후 "(코어 덤프)"가 표시됩니다.

분할 오류 : 11 (코어 덤프)

참조 : 코어 덤프 -하지만 핵심 파일이 현재 디렉토리에 있지?


우분투

우분투에서 코어 덤프는 Apport에 의해 처리되며 에 위치 할 수 있습니다 /var/crash/. 그러나 안정적인 릴리스에서는 기본적으로 비활성화되어 있습니다.

자세한 내용 은 Ubuntu에서 코어 덤프를 어디서 찾을 수 있습니까? 를 확인하십시오. .

맥 OS

macOS의 경우 : Mac OS X에서 코어 덤프를 생성하는 방법은 무엇입니까?


3
우분투의 경우, 정상적인 동작으로 빠르게 되돌리려면 (현재 디렉토리에 코어 파일 덤핑) "sudo service apport stop"으로 apport 서비스를 중지하십시오. 또한 docker 내에서 실행중인 경우 해당 설정은 컨테이너가 아닌 호스트 시스템에서 제어됩니다.
— Digicrat

26

내가 마지막에 한 것은 충돌하기 전에 프로세스에 gdb를 첨부 한 다음 segfault를 얻었을 때 나는 generate-core-file명령을 실행했다 . 이로 인해 코어 덤프가 생성되었습니다.


프로세스에 gdb를 어떻게 첨부 했습니까?
— Chani

6
Ritwik G에 응답하려면 프로세스를 gdb에 첨부하려면 gdb를 시작하고 'attach <pid>'를 입력하십시오. 여기서 <pid>는 첨부 할 프로세스의 pid 번호입니다.
— Jean-Dominique Frattini 2016 년

(약칭 ge)
— user202729 2016 년

새로운 질문이 있으면 의견을 묻는 대신 새로운 질문 을해야합니다 .
— user202729 2016 년

이상한 것은이 이미 설정되어 있지 않은 ulimit -c으로 unlimited하지만, 코어 파일이 더 만들어 잠잠되면, generate-core-fileGDB 세션에서 파일 덕분에 코어 파일을 생성한다.
— CodyChan

19

어쩌면 이런 식으로 할 수 있습니다.이 프로그램은 세그먼테이션 오류를 포착하고 디버거 (이것은 아래에서 사용되는 원래 코드 AIX임)에 쉘을 트랩하는 방법을 보여주고 스택 추적을 세그먼테이션 오류 지점까지 인쇄합니다. Linux의 경우 sprintf사용할 변수 를 변경해야합니다 gdb.

#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 */
}

이 블로그의 여기 에 표시된대로 gdb가 코어를 덤프하도록 매개 변수를 추가해야 할 수도 있습니다 .


16

코어 덤프 생성에 영향을 줄 수있는 것들이 더 있습니다. 나는 이것들을 만났다 :

  • 덤프 디렉토리는 쓰기 가능해야합니다. 기본적으로 이것은 프로세스의 현재 디렉토리이지만 설정으로 변경 될 수 있습니다 /proc/sys/kernel/core_pattern.
  • 일부 조건에서 커널 값 /proc/sys/fs/suid_dumpable은 코어 생성을 방해 할 수 있습니다.

매뉴얼 페이지에 설명 된 생성을 방해 할 수있는 상황이 더 있습니다 man core.


9

코어 덤프를 활성화하려면 다음을 수행하십시오.

  1. 에서 /etc/profile코멘트 라인 :

    # ulimit -S -c 0 > /dev/null 2>&1
  2. 에서 /etc/security/limits.conf라인 밖으로 코멘트 :

    *               soft    core            0
  3. cmd를 실행하고 cmd limit coredumpsize unlimited로 확인하십시오 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. kill -s SEGV <PID>코어 파일이 작성되었는지 확인하려면 cmd를 사용하여 관련 프로세스를 종료 할 수 있습니다 (코어 파일이 작성되지 않은 경우이를 확인으로 사용할 수 있음).

    # kill -s SEGV <PID>

코어 파일이 작성되면 관련 파일 (1./2./3.)에서 코어 덤프 설정을 다시 비활성화하십시오.


9

우분투 14.04

  1. 코어 덤프 활성화 확인 :

    ulimit -a
  2. 라인 중 하나는 다음과 같아야합니다.

    core file size          (blocks, -c) unlimited
  3. 그렇지 않은 경우 :

    gedit ~/.bashrculimit -c unlimited파일 끝에 추가 하고 저장하고 터미널을 다시 실행하십시오.

  4. 디버그 정보로 애플리케이션을 빌드하십시오.

    Makefile에서 -O0 -g

  5. 코어 덤프를 작성하는 애플리케이션을 실행하십시오 (이름이 'core'인 코어 덤프 파일은 application_name 파일 근처에 작성되어야 함).

    ./application_name
  6. gdb에서 실행하십시오.

    gdb application_name core

3 단계에서 터미널을 '재실행'하는 방법은 무엇입니까? 재부팅을 의미합니까?
— Naveen

@Naveen no, 터미널을 닫고 새 것을 열면 ulimit -c unlimited터미널 솔루션을 수정 ~/.bashrc해야 변경 사항이 적용 되므로 임시 솔루션을 위해 터미널에 넣을 수도 있습니다 .
— mrgloom 2016 년

4

기본적으로 코어 파일이 제공됩니다. 프로세스의 현재 디렉토리가 쓰기 가능하거나 코어 파일이 작성되지 않았는지 확인하십시오.


4
"프로세스의 현재 디렉토리"는 프로세스가 실행될 때 $ cwd를 의미합니까? ~ / abc> / usr / bin / cat def cat이 충돌하면 현재 디렉토리가 ~ / abc 또는 / usr / bin입니까?
— Nathan Fellman

5
~ / abc. 흠, 댓글의 길이는 15 자 여야합니다!
— Mark Harrison

5
이것은 SEGV 시점의 현재 디렉토리입니다. 또한 실제 사용자 / 그룹과 다른 유효 사용자 및 / 또는 그룹으로 실행되는 프로세스는 코어 파일을 쓰지 않습니다.
— Darron

2

system call을 사용하여 프로그래밍 방식으로 코어 덤프를 설정하는 것이 setrlimit좋습니다.

예:

#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));
}

왜 더 나은가요?
— Nathan Fellman

충돌 후 생성 된 코어 파일 ulimit -c unlimited은 명령 행 환경에서 필요하지 않은 다음 응용 프로그램을 다시 실행하십시오.
— kgbook

사용자가 개발자에게 연락하여 볼 때만 충돌 할 때마다 코어 덤프를 원하지 않습니다. 100 번 충돌하면 100 개의 코어 덤프가 필요하지 않습니다.
— Nathan Fellman

그 경우에는 사용하는 것이 좋습니다 ulimit -c unlimited. 또한 마르코 정의로 컴파일 할 수 있으며, enable_core_dump릴리스시 매크로를 정의 하지 않으면 응용 프로그램에 기호가 포함 되지 않으며 디버그 버전으로 코어 덤프 대체가 제공됩니다.
— kgbook

매크로에 의해 자격이 되더라도 다시 실행하기 전에 단순히 쉘에서 명령을 실행하는 대신 코어 덤프를 생성하려면 다시 컴파일해야합니다.
— Nathan Fellman

1

당신이있는 경우에 있다는 언급이의 가치 systemd 세트를, 다음 일들이 조금 다릅니다. 설정은 일반적으로 core_patternsysctl 값을 통해 코어 파일이 파이프되도록 합니다 systemd-coredump(8). 코어 파일 크기 rlimit는 일반적으로 이미 "무제한"으로 구성되어 있습니다.

그런 다음을 사용하여 코어 덤프를 검색 할 수 있습니다 coredumpctl(1).

코어 덤프 등의 스토리지는로 구성됩니다 coredump.conf(5). coredumpctl 매뉴얼 페이지에서 코어 파일을 얻는 방법에 대한 예가 있지만 간단히 말하면 다음과 같습니다.

핵심 파일을 찾으십시오.

[vps@phoenix]~$ coredumpctl list test_me | tail -1
Sun 2019-01-20 11:17:33 CET   16163  1224  1224  11 present /home/vps/test_me

핵심 파일을 얻으십시오 :

[vps@phoenix]~$ coredumpctl -o test_me.core dump 16163

0

우분투 19.04

다른 모든 답변 자체는 저에게 도움이되지 않았습니다. 그러나 다음 요약은 일을했습니다.

~/.config/apport/settings다음 내용으로 작성하십시오 .

[main]
unpackaged=true

(이것은 apport가 커스텀 앱을위한 핵심 덤프를 작성하도록 지시합니다)

확인 : ulimit -c. 0을 출력하면

ulimit -c unlimited

경우에 대비하여 apport를 다시 시작하십시오.

sudo systemctl restart apport

충돌 파일이 작성되었습니다 /var/crash/. 그러나 gdb와 함께 사용할 수 없습니다 . gdb와 함께 사용하려면

apport-unpack <location_of_report> <target_directory>

추가 정보 :

  • 일부 답변은 변경을 제안 core_pattern합니다. 다시 시작할 때 apport 서비스가 해당 파일을 덮어 쓸 수 있습니다.
  • 단순히 apport를 중지하면 작업이 수행되지 않았습니다.
  • ulimit -c당신이 웹의 다른 답변을 시도하는 동안 값이 자동으로 변경 얻을 수 있습니다. 코어 덤프 작성을 설정하는 동안 정기적으로 확인하십시오.

참고 문헌 :

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.