Когда процесс получает SIGABRT (сигнал 6)?
8 ответов
abort()
отправляет вызывающий процесс SIGABRT
сигнал, это как abort()
в основном работает.
abort()
обычно вызывается библиотечными функциями, которые обнаруживают внутреннюю ошибку или какое-либо серьезно нарушенное ограничение. Например malloc()
будем называть abort()
если его внутренние структуры повреждены переполнение кучи.
вы можете отправить любой сигнал в любой процесс, используя kill(2)
интерфейс:
kill -SIGABRT 30823
30823 был dash
процесс я начал, поэтому я мог легко найти процесс, который я хотел убить.
$ /bin/dash
$ Aborted
на Aborted
выход, по-видимому, как dash
сообщает SIGABRT.
его можно отправить сразу в любой процесс используя kill(2)
, или процесс может отправить сигнал себе через assert(3)
, abort(3)
или raise(3)
.
SIGABRT
обычно используется libc и другими библиотеками для прерывания программы в случае критических ошибок. Например, glibc отправляет SIGABRT
в случае обнаруженных двойн-свободных или других повреждений кучи.
кроме того, большинство assert
реализации используют SIGABRT
в случае не утверждать.
кроме того, SIGABRT
может быть отправлен из любого другого процесса, как и любой другой сигнал. Конечно, процесс отправки должен выполняться как тот же пользователь или root.
обычно это происходит, когда возникает проблема с выделением памяти.
Это случилось со мной, когда я моя программа пытается выделить массив с отрицательным размером.
есть еще одна простая причина в случае c++.
std::thread::~thread{
if((joinable ())
std::terminate ();
}
т. е. область потока закончилась, но вы забыли позвонить либо
thread::join();
или
thread::detach();
GNU libc распечатает информацию в /dev/tty
по какой-то роковой условия перед вызовом abort()
(который затем инициирует SIGABRT
), но если вы используете свою программу как службу или иначе не в реальном окне терминала, это сообщение может потеряться, потому что нет tty для отображения сообщений.
см. мой пост о перенаправлении libc для записи в stderr вместо /dev/tty:
ловить сообщения об ошибках libc, перенаправляя из / dev / tty
случай, когда процесс получает SIGABRT от себя: Hrvoje упомянул о похороненном чистом виртуальном существе, вызванном из ctor, генерирующего аборт, я воссоздал пример для этого. Вот когда будет построен, он сначала вызывает конструктор своего базового класса, и передает внутрь указатель на себя. a ctor вызывает чистый виртуальный метод до заполнения таблицы допустимым указателем, потому что 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;
}
compile: g++ - o aa aa.cpp
параметр ulimit -с неограниченный
run: ./ 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
проверить код:
disas 0x7feae3170c37
mov xea,%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
:)
в моем случае это было связано с входом в массив с индексом, равным длине массива.
string x[5];
for(int i=1; i<=5; i++){
cin>>x[i];
}
x[5] доступен, которого нет.