Quand un processus reçoit-il SIGABRT (signal 6)?
8 réponses
abort()
envoie au processus d'appel le signal SIGABRT
, c'est comme ça que abort()
fonctionne.
abort()
est généralement appelé par les fonctions de la bibliothèque qui détectent une erreur interne ou une contrainte sérieusement brisée. Par exemple malloc()
appellera abort()
si ses structures internes sont endommagées par un débordement de tas.
vous pouvez envoyer n'importe quel signal à n'importe quel processus en utilisant l'interface kill(2)
:
kill -SIGABRT 30823
30823 était un dash
processus que j'ai commencé, donc je pouvais facilement trouver le processus que je voulais tuer.
$ /bin/dash
$ Aborted
la sortie Aborted
est apparemment la façon dont dash
rapporte un SIGABRT.
il peut être envoyé directement à n'importe quel processus en utilisant kill(2)
, ou un processus peut envoyer le signal à lui-même via assert(3)
, abort(3)
, ou raise(3)
.
SIGABRT
est couramment utilisé par libc et d'autres bibliothèques pour annuler le programme en cas d'erreurs critiques. Par exemple, glibc envoie un SIGABRT
dans le cas d'un double-libre détecté ou d'autres corruptions tas.
aussi, la plupart des implémentations de assert
utilisent SIGABRT
en cas de défaillance d'une assertion.
de plus, SIGABRT
peut être envoyé de n'importe quel autre processus comme n'importe quel autre signal. Bien sûr, le processus d'envoi des besoins de exécutez en tant que même utilisateur ou root.
cela se produit généralement quand il ya un problème avec l'allocation de mémoire.
il m'est arrivé quand j'ai mon programme essayait d'allouer un tableau avec une taille négative.
il y a une autre cause simple en cas de c++.
std::thread::~thread{
if((joinable ())
std::terminate ();
}
c'est-à-dire que la portée du fil s'est terminée, mais vous avez oublié d'appeler l'un ou l'autre
thread::join();
ou
thread::detach();
la libc GNU imprimera des informations à /dev/tty
concernant certaines conditions fatales avant d'appeler abort()
(qui déclenche alors SIGABRT
), mais si vous exécutez votre programme comme un service ou autrement pas dans une fenêtre de terminal réelle, ces messages peuvent être perdus, parce qu'il n'y a pas d'ATS pour afficher les messages.
Voir mon article sur la redirection de libc pour écrire à stderr au lieu de/dev / tty:
"151980920 de" Capture de la libc messages d'erreur, redirection de / dev / tty
un cas où le processus obtenir SIGABRT de lui-même: Hrvoje a mentionné au sujet d'un être virtuel enterré pur appelé de ctor générant un abandon, j'ai recréé un exemple pour ceci. Ici, quand d doit être construit, il appelle d'abord sa classe de base un acteur, et passe à l'intérieur de pointeur à lui-même. l'ator appelle la méthode virtuelle pure avant que la table ne soit remplie avec un pointeur valide, parce que d n'est pas encore construit.
#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;
}
compiler: g++ - O aa aa.cpp
ulimit-c illimité
run:./ aa
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
permet maintenant de voir rapidement le fichier de base, et de valider que SIGABRT a bien été appelé:
gdb aa core
voir Règl."
i r
rdx 0x6 6
rsi 0x69a 1690
rdi 0x69a 1690
rip 0x7feae3170c37
code de contrôle:
disas 0x7feae3170c37
mov "151940920"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
:)
Dans mon cas, c'était dû à une entrée dans un tableau à un indice égal à la longueur du tableau.
string x[5];
for(int i=1; i<=5; i++){
cin>>x[i];
}
x[5] est en cours d'accès qui n'est pas présent.