Подтвердить что ты не робот

Когда процесс получает SIGABRT (сигнал 6)?

Каковы сценарии, когда процесс получает SIGABRT в С++? Всегда ли этот сигнал поступает из процесса или может ли этот сигнал посылаться из одного процесса в другой?

Есть ли способ определить, какой процесс отправляет этот сигнал?

4b9b3361

Ответ 1

abort() отправляет вызывающему процессу сигнал SIGABRT, как это работает abort().

abort() обычно вызывается библиотечными функциями, которые обнаруживают внутреннюю ошибку или какое-то серьезно нарушенное ограничение. Например, malloc() вызовет abort(), если его внутренние структуры повреждены переполнением кучи.

Ответ 2

Вы можете отправить любой сигнал в любой процесс с помощью интерфейса kill(2):

kill -SIGABRT 30823

30823 был процессом dash, который я начал, поэтому я мог легко найти процесс, который я хотел убить.

$ /bin/dash
$ Aborted

Вывод Aborted, по-видимому, показывает, как dash сообщает SIGABRT.

Он может быть отправлен непосредственно в любой процесс с помощью kill(2), или процесс может отправить сигнал самому себе через assert(3), abort(3) или raise(3).

Ответ 3

SIGABRT обычно используется libc и другими библиотеками для прерывания работы программы в случае критических ошибок. Например, glibc отправляет SIGABRT в случае обнаружения двойного освобождения или других повреждений кучи.

Кроме того, большинство реализаций assert используют SIGABRT в случае неудачного утверждения.

Кроме того, SIGABRT может быть отправлен из любого другого процесса, как и любой другой сигнал. Конечно, процесс отправки должен запускаться от имени того же пользователя или пользователя root.

Ответ 4

Обычно это происходит, когда есть проблема с выделением памяти.

Это случилось со мной, когда моя программа пыталась выделить массив с отрицательным размером.

Ответ 5

Есть еще одна простая причина в случае С++.

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

то есть. объем потока закончился, но вы забыли позвонить либо

thread::join();

или

thread::detach();

Ответ 6

GNU libc будет распечатывать информацию в /dev/tty относительно некоторых фатальных условий до того, как он вызовет abort() (который затем вызывает SIGABRT), но если вы запускаете свою программу как услугу или иначе не находитесь в реальном терминале окно, это сообщение может потеряться, потому что нет сообщений tty для отображения сообщений.

См. мой пост по перенаправлению libc для записи в stderr вместо /dev/tty:

Обход сообщений об ошибках libc, перенаправление из/dev/tty

Ответ 7

Случай, когда процесс получает SIGABRT от себя: Хрвое упомянул о захороненном чистом виртуальном существе, вызванном из ctor, создающем прерывание, и я воссоздал пример этого. Здесь, когда d должен быть построен, он сначала называет его базовый класс A 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;
}

скомпилировать: g++ -o aa aa.cpp

ulimit -c неограниченный

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    $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

:)

Ответ 8

В моем случае это произошло из-за ввода в массив с индексом, равным длине массива.

string x[5];

for(int i=1; i<=5; i++){

    cin>>x[i];

}

x [5], к которому нет доступа.

Ответ 9

Я дам свой ответ с точки зрения конкурентного программирования (cp), но он применим и к другим доменам.

Во многих случаях при выполнении cp ограничения довольно велики.

Например,: у меня был вопрос с переменными N, M, Q, такими, что 1 ≤ N, M, Q < 10^5.

Ошибка, которую я совершил, заключалась в том, что я объявил двумерный целочисленный массив размером 10000 x 10000 в C++ и боролся с ошибкой SIGABRT в Codechef в течение почти 2 дней.

Теперь, если мы посчитаем:

Типичный размер целого числа: 4 байта

No. of cells in our array: 10000 x 10000

Total size (in bytes): 400000000 bytes = 4*10^8 ≈ 400 MB

Ваши решения таких вопросов будут работать на вашем компьютере (не всегда), поскольку он может позволить себе такой размер.

Но ресурсы на сайтах кодирования (онлайн-судьи) ограничены несколькими килобайтами.

Следовательно, ошибка SIGABRT и другие подобные ошибки.

Вывод:

В таких вопросах нам не следует объявлять массив, вектор или любой другой DS такого размера, но наша задача - сделать наш алгоритм настолько эффективным, чтобы он работал без них (DS) или с меньшим объемом памяти.

PS: возможны другие причины этой ошибки; выше был один из них.