В каких сценариях процесс получает SIGABRT на C ++? Всегда ли этот сигнал поступает из процесса или этот сигнал может передаваться от одного процесса к другому?
Есть ли способ определить, какой процесс посылает этот сигнал?
В каких сценариях процесс получает SIGABRT на C ++? Всегда ли этот сигнал поступает из процесса или этот сигнал может передаваться от одного процесса к другому?
Есть ли способ определить, какой процесс посылает этот сигнал?
Ответы:
abort()
посылает вызывающему процессу SIGABRT
сигнал, вот как abort()
это работает в принципе.
abort()
обычно вызывается библиотечными функциями, которые обнаруживают внутреннюю ошибку или какое-то серьезно нарушенное ограничение. Например malloc()
, вызовет, abort()
если его внутренние структуры повреждены переполнением кучи.
libc
попытке вызвать free()
неинициализированный / поврежденный указатель
Close()
метода, поэтому он был забыт. Был отличный охват, хотя. : Rolleyes:
SIGABRT
обычно используется libc и другими библиотеками для прерывания работы программы в случае критических ошибок. Например, glibc отправляет сообщение SIGABRT
в случае обнаружения двойного свободного или другого повреждения кучи.
Кроме того, большинство assert
реализаций используют SIGABRT
в случае неудачного утверждения.
Кроме того, SIGABRT
может быть отправлен из любого другого процесса, как любой другой сигнал. Конечно, процесс отправки должен запускаться от имени того же пользователя или пользователя root.
Вы можете отправить любой сигнал любому процессу, используя kill(2)
интерфейс:
kill -SIGABRT 30823
30823 - это dash
процесс, который я начал, поэтому я мог легко найти процесс, который хотел убить.
$ /bin/dash
$ Aborted
Aborted
Выход, по- видимому , как dash
сообщает SIGABRT.
Он может быть направлен непосредственно к любому процессу , используя kill(2)
, или процесс может послать сигнал на себе с помощью assert(3)
, abort(3)
или raise(3)
.
Есть еще одна простая причина в случае с ++.
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, генерирующем прерывание, я воссоздал пример этого. Здесь, когда d должен быть сконструирован, он сначала вызывает свой ctor базового класса A и передает внутрь указатель на себя. 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 ++ -a aa aa.cpp
ulimit -c неограниченно
запустить: ./aa
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
Теперь давайте быстро увидим файл ядра и подтвердим, что SIGABRT действительно был вызван:
gdb aa core
смотри regs:
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
:)
Как метко указано «@sarnold», любой процесс может отправлять сигнал любому другому процессу, следовательно, один процесс может отправлять SIGABORT другому процессу, и в этом случае принимающий процесс не может различить, приходит ли он из-за собственной настройки память и т. д., или кто-то еще «одноадресно», отправьте на него.
В одной из систем, с которой я работал, есть один тупиковый детектор, который фактически определяет, выходит ли процесс из какой-либо задачи, с помощью биения сердца или нет. Если нет, то он объявляет, что процесс находится в тупиковом состоянии, и отправляет SIGABORT.
Я просто хотел поделиться этой перспективой со ссылкой на заданный вопрос.
Я дам свой ответ с точки зрения конкурентного программирования (cp) , но это относится и к другим областям.
Много раз при выполнении команды cp ограничения достаточно велики.
Например : у меня был вопрос с N, M, Q
такими переменными , что 1 ≤ N, M, Q < 10^5
.
Ошибка , которую я делал я был объявлен 2D массив целых чисел размером 10000 x 10000
в C++
и боролись сSIGABRT
ошибкой в Codechef в течение почти 2 дней.
Теперь, если мы посчитаем:
Типичный размер целого числа: 4 байта
Количество ячеек в нашем массиве: 10000 х 10000
Общий размер (в байтах): 400000000 байт = 4 * 10 ^ 8 ≈ 400 МБ
Ваши решения таких вопросов будут работать на вашем компьютере (не всегда), поскольку он может позволить себе такой размер.
Но ресурсы на сайтах кодирования (онлайн-судьи) ограничены несколькими килобайтами.
Отсюда и SIGABRT
ошибки и другие подобные ошибки.
Вывод:
В таких вопросах нам не следует объявлять массив, вектор или любой другой DS такого размера, но наша задача - сделать наш алгоритм настолько эффективным, чтобы он работал без них (DS) или с меньшим объемом памяти.
PS : могут быть и другие причины этой ошибки; выше был один из них.