프로세스가 C ++에서 SIGABRT를 얻는 시나리오는 무엇입니까? 이 신호는 항상 프로세스 내에서 오거나이 신호를 한 프로세스에서 다른 프로세스로 보낼 수 있습니까?
이 신호를 보내는 프로세스를 식별하는 방법이 있습니까?
답변
abort()
호출 프로세스에 SIGABRT
신호를 보내면 abort()
기본적으로 작동합니다.
abort()
일반적으로 내부 오류 또는 심각하게 손상된 제약 조건을 감지하는 라이브러리 함수에 의해 호출됩니다. 예를 들어 내부 구조가 힙 오버플로로 인해 손상된 경우 malloc()
호출 abort()
합니다.
답변
SIGABRT
libc 및 기타 라이브러리에서 일반적으로 심각한 오류가 발생할 경우 프로그램을 중단하는 데 사용됩니다. 예를 들어, glibc는 SIGABRT
이중 프리 또는 기타 힙 손상이 감지 된 경우를 보냅니다 .
또한 대부분의 assert
구현에서는 SIGABRT
어설 션이 실패한 경우를 사용합니다.
또한 SIGABRT
다른 신호와 같은 다른 프로세스에서 전송할 수 있습니다. 물론 전송 프로세스는 동일한 사용자 또는 루트로 실행해야합니다.
답변
kill(2)
인터페이스를 사용하여 모든 프로세스에 신호를 보낼 수 있습니다 .
kill -SIGABRT 30823
30823은 dash
내가 시작한 프로세스이므로 내가 죽이고 싶었던 프로세스를 쉽게 찾을 수있었습니다.
$ /bin/dash
$ Aborted
Aborted
출력하는 방법을 분명히입니다 dash
SIGABRT를보고합니다.
그것은 사용하는 프로세스에 직접적으로 전송 될 수있다 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를 재지 정하는 내 게시물을 참조하십시오.
답변
프로세스가 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
🙂