프로세스는 언제 SIGABRT (신호 6)를 얻습니까? ++에서 SIGABRT를 얻는 시나리오는

프로세스가 C ++에서 SIGABRT를 얻는 시나리오는 무엇입니까? 이 신호는 항상 프로세스 내에서 오거나이 신호를 한 프로세스에서 다른 프로세스로 보낼 수 있습니까?

이 신호를 보내는 프로세스를 식별하는 방법이 있습니까?



답변

abort()호출 프로세스에 SIGABRT신호를 보내면 abort()기본적으로 작동합니다.

abort()일반적으로 내부 오류 또는 심각하게 손상된 제약 조건을 감지하는 라이브러리 함수에 의해 호출됩니다. 예를 들어 내부 구조가 힙 오버플로로 인해 손상된 경우 malloc()호출 abort()합니다.


답변

SIGABRTlibc 및 기타 라이브러리에서 일반적으로 심각한 오류가 발생할 경우 프로그램을 중단하는 데 사용됩니다. 예를 들어, glibc는 SIGABRT이중 프리 또는 기타 힙 손상이 감지 된 경우를 보냅니다 .

또한 대부분의 assert구현에서는 SIGABRT어설 션이 실패한 경우를 사용합니다.

또한 SIGABRT다른 신호와 같은 다른 프로세스에서 전송할 수 있습니다. 물론 전송 프로세스는 동일한 사용자 또는 루트로 실행해야합니다.


답변

kill(2)인터페이스를 사용하여 모든 프로세스에 신호를 보낼 수 있습니다 .

kill -SIGABRT 30823

30823은 dash내가 시작한 프로세스이므로 내가 죽이고 싶었던 프로세스를 쉽게 찾을 수있었습니다.

$ /bin/dash
$ Aborted

Aborted출력하는 방법을 분명히입니다 dashSIGABRT를보고합니다.

그것은 사용하는 프로세스에 직접적으로 전송 될 수있다 kill(2), 또는 프로세스를 통해 자신에게 신호를 보낼 수있는 assert(3), abort(3)또는 raise(3).


답변

일반적으로 메모리 할당에 문제가있을 때 발생합니다.

내 프로그램이 음의 크기로 배열을 할당하려고 할 때 나에게 일어났다.


답변

C ++의 경우 또 다른 간단한 원인이 있습니다.

std::thread::~thread{
    if((joinable ())
        std::terminate ();
}

즉 스레드의 범위가 종료되었지만 호출하는 것을 잊어 버렸습니다.

thread::join();

또는

thread::detach();


답변

GNU libc는 /dev/tty호출하기 전에 몇 가지 치명적인 조건 에 관한 정보를 출력 하지만 abort()(이는 트리거 됨 SIGABRT) 프로그램을 서비스로 실행 중이거나 실제 터미널 창에서 실행하지 않으면 이러한 메시지가 없어 질 수 있습니다. tty는 메시지를 표시합니다.

/ dev / tty 대신 stderr에 쓰도록 libc를 재지 정하는 내 게시물을 참조하십시오.

/ dev / tty에서 리디렉션하는 libc 오류 메시지 잡기


답변

프로세스가 SIGABRT를 가져 오는 경우 : Hrvoje는 중단을 생성하는 ctor에서 호출 된 묻힌 순수 가상에 대해 언급했으며 이에 대한 예를 다시 작성했습니다. 여기서 d가 생성 될 때, 먼저 기본 클래스 A ctor를 호출하고 내부 포인터를 자신에게 전달합니다. c는 d가 아직 구성되지 않았기 때문에 테이블이 유효한 포인터로 채워지기 전에 순수 가상 메소드를 호출합니다.

#include<iostream>
using namespace std;
class A {
public:
 A(A *pa){pa->f();}
 virtual void f()=0;
};
class D : public A {
public:
 D():A(this){}
 virtual void f() {cout<<"D::f\n";}
};
int main(){
 D d;
 A *pa = &d;
 pa->f();
 return 0;
}

컴파일 : g ++ -o aa aa.cpp

ulimit -c 무제한

실행 : ./aa

pure virtual method called
terminate called without an active exception
Aborted (core dumped)

이제 핵심 파일을 빠르게보고 SIGABRT가 실제로 호출되었는지 확인하십시오.

gdb aa core

등록 참조 :

i r
rdx            0x6      6
rsi            0x69a    1690
rdi            0x69a    1690
rip            0x7feae3170c37

체크 코드 :

장애 0x7feae3170c37

mov    $0xea,%eax  = 234  <- this is the kill syscall, sends signal to process
syscall   <-----

http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/

234 sys_tgkill pid_t tgid pid_t pid int sig = 6 = SIGABRT

🙂