В каких сценариях процесс получает SIGABRT на C ++? Всегда ли этот сигнал поступает из процесса или этот сигнал может передаваться от одного процесса к другому?
Есть ли способ определить, какой процесс посылает этот сигнал?
Есть несколько способов. Самый простой способ, если вы написали программу, это зарегистрировать обработчик сигнала для SIGABRT, который распечатывает эту информацию и очищает ее потоки перед возвратом. Второй самый простой способ - запустить программу в рамках strace. Третий самый простой способ - убедиться, что программа генерирует файл ядра в случае сбоя, и выяснить это через дамп ядра.
Парфянский выстрел
Ответы:
195
abort()посылает вызывающему процессу SIGABRTсигнал, вот как abort()это работает в принципе.
abort()обычно вызывается библиотечными функциями, которые обнаруживают внутреннюю ошибку или какое-то серьезно нарушенное ограничение. Например malloc(), вызовет, abort()если его внутренние структуры повреждены переполнением кучи.
для меня в большинстве случаев SIGABRT был отправлен при libcпопытке вызвать free()неинициализированный / поврежденный указатель
grandrew
Если бы я где-то в коде скрыл чисто виртуальный вызов функции из конструктора, может ли это также привести к сигналу SIGABRT? Я спрашиваю, поскольку я вижу ошибку, утверждающую, что у меня есть чистый виртуальный вызов, и следующая строка дает мне сообщение SIGABRT, и приложение или аварийно завершает работу или закрывается операционной системой. Спасибо.
Hrvoje
2
На MacOS мы получили SIGABRT для открытия около 1000 файловых дескрипторов без их закрытия. Вместо насмешек наши тесты абстрагировали файл с более общим типом читателя, у которого нет Close()метода, поэтому он был забыт. Был отличный охват, хотя. : Rolleyes:
Зил
52
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).
GNU libc распечатает информацию /dev/ttyо некоторых фатальных состояниях до того, как она abort()вызовет (что затем сработает SIGABRT), но если вы запускаете свою программу как службу или иным образом не в реальном окне терминала, эти сообщения могут быть потеряны, потому что нет tty для отображения сообщений.
Смотрите мой пост о перенаправлении libc для записи в stderr вместо / dev / tty:
Случай, когда процесс получает SIGABRT от самого себя: Hrvoje упомянул о скрытом чистом виртуальном существе, вызываемом из ctor, генерирующем прерывание, я воссоздал пример этого. Здесь, когда d должен быть сконструирован, он сначала вызывает свой ctor базового класса A и передает внутрь указатель на себя. A ctor вызывает чисто виртуальный метод до того, как таблица заполнена корректным указателем, потому что d еще не создано.
#include<iostream>usingnamespace std;class A {public:
A(A *pa){pa->f();}virtualvoid f()=0;};class D :public A {public:
D():A(this){}virtualvoid f(){cout<<"D::f\n";}};int main(){
D d;
A *pa =&d;
pa->f();return0;}
компилировать: 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 0x66
rsi 0x69a1690
rdi 0x69a1690
rip 0x7feae3170c37
контрольный код:
disas 0x7feae3170c37
mov $0xea,%eax =234<-this is the kill syscall, sends signal to process
syscall <-----
Как метко указано «@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 : могут быть и другие причины этой ошибки; выше был один из них.
Ответы:
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
процесс, который я начал, поэтому я мог легко найти процесс, который хотел убить.Aborted
Выход, по- видимому , какdash
сообщает SIGABRT.Он может быть направлен непосредственно к любому процессу , используя
kill(2)
, или процесс может послать сигнал на себе с помощьюassert(3)
,abort(3)
илиraise(3)
.источник
Обычно это происходит, когда есть проблема с выделением памяти.
Это случилось со мной, когда моя программа пыталась выделить массив с отрицательным размером.
источник
Есть еще одна простая причина в случае с ++.
т. е. объем потока закончился, но вы забыли позвонить либо
или
источник
GNU libc распечатает информацию
/dev/tty
о некоторых фатальных состояниях до того, как онаabort()
вызовет (что затем сработаетSIGABRT
), но если вы запускаете свою программу как службу или иным образом не в реальном окне терминала, эти сообщения могут быть потеряны, потому что нет tty для отображения сообщений.Смотрите мой пост о перенаправлении libc для записи в stderr вместо / dev / tty:
Перехват сообщений об ошибках libc, перенаправление из / dev / tty
источник
Случай, когда процесс получает SIGABRT от самого себя: Hrvoje упомянул о скрытом чистом виртуальном существе, вызываемом из ctor, генерирующем прерывание, я воссоздал пример этого. Здесь, когда d должен быть сконструирован, он сначала вызывает свой ctor базового класса A и передает внутрь указатель на себя. A ctor вызывает чисто виртуальный метод до того, как таблица заполнена корректным указателем, потому что d еще не создано.
компилировать: g ++ -a aa aa.cpp
ulimit -c неограниченно
запустить: ./aa
Теперь давайте быстро увидим файл ядра и подтвердим, что SIGABRT действительно был вызван:
смотри regs:
контрольный код:
disas 0x7feae3170c37
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
:)
источник
В моем случае это произошло из-за ввода в массив с индексом, равным длине массива.
Доступ к x [5], которого нет.
источник
Как метко указано «@sarnold», любой процесс может отправлять сигнал любому другому процессу, следовательно, один процесс может отправлять SIGABORT другому процессу, и в этом случае принимающий процесс не может различить, приходит ли он из-за собственной настройки память и т. д., или кто-то еще «одноадресно», отправьте на него.
В одной из систем, с которой я работал, есть один тупиковый детектор, который фактически определяет, выходит ли процесс из какой-либо задачи, с помощью биения сердца или нет. Если нет, то он объявляет, что процесс находится в тупиковом состоянии, и отправляет SIGABORT.
Я просто хотел поделиться этой перспективой со ссылкой на заданный вопрос.
источник
Я дам свой ответ с точки зрения конкурентного программирования (cp) , но это относится и к другим областям.
Много раз при выполнении команды cp ограничения достаточно велики.
Например : у меня был вопрос с
N, M, Q
такими переменными , что1 ≤ N, M, Q < 10^5
.Ошибка , которую я делал я был объявлен 2D массив целых чисел размером
10000 x 10000
вC++
и боролись сSIGABRT
ошибкой в Codechef в течение почти 2 дней.Теперь, если мы посчитаем:
Ваши решения таких вопросов будут работать на вашем компьютере (не всегда), поскольку он может позволить себе такой размер.
Но ресурсы на сайтах кодирования (онлайн-судьи) ограничены несколькими килобайтами.
Отсюда и
SIGABRT
ошибки и другие подобные ошибки.Вывод:
В таких вопросах нам не следует объявлять массив, вектор или любой другой DS такого размера, но наша задача - сделать наш алгоритм настолько эффективным, чтобы он работал без них (DS) или с меньшим объемом памяти.
PS : могут быть и другие причины этой ошибки; выше был один из них.
источник