Quels sont les scénarios où un processus obtient un SIGABRT en C ++? Ce signal provient-il toujours du processus ou peut-il être envoyé d'un processus à un autre?
Existe-t-il un moyen d'identifier le processus qui envoie ce signal?
Quels sont les scénarios où un processus obtient un SIGABRT en C ++? Ce signal provient-il toujours du processus ou peut-il être envoyé d'un processus à un autre?
Existe-t-il un moyen d'identifier le processus qui envoie ce signal?
Réponses:
abort()
envoie le processus appelant le SIGABRT
signal, abort()
voici comment fonctionne fondamentalement.
abort()
est généralement appelé par des fonctions de bibliothèque qui détectent une erreur interne ou une contrainte sérieusement rompue. Par exemple malloc()
, appellera abort()
si ses structures internes sont endommagées par un débordement de tas.
libc
essayant d'appeler free()
un pointeur non initialisé / corrompu
Close()
méthode, donc il a été oublié. Avait une grande couverture cependant. : rolleyes:
SIGABRT
est couramment utilisé par libc et d'autres bibliothèques pour abandonner le programme en cas d'erreurs critiques. Par exemple, la glibc envoie un SIGABRT
en cas de corruption de tas double ou autre détectée.
De plus, la plupart des assert
implémentations utilisent SIGABRT
en cas d'échec d'une assertion.
En outre, SIGABRT
peut être envoyé à partir de tout autre processus comme tout autre signal. Bien sûr, le processus d'envoi doit s'exécuter en tant que même utilisateur ou racine.
Vous pouvez envoyer n'importe quel signal à n'importe quel processus en utilisant l' kill(2)
interface:
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 Aborted
sortie est apparemment comment dash
rapporte un SIGABRT.
Il peut être envoyé directement à tout processus en utilisant kill(2)
, ou un processus peut envoyer le signal à lui - même via assert(3)
, abort(3)
ou raise(3)
.
Il y a une autre cause simple en cas de c ++.
std::thread::~thread{
if((joinable ())
std::terminate ();
}
c.-à-d. portée du fil terminé mais vous avez oublié d'appeler
thread::join();
ou
thread::detach();
La libc GNU imprimera des informations /dev/tty
concernant certaines conditions fatales avant d'appeler abort()
(ce qui se déclenche ensuite SIGABRT
), mais si vous exécutez votre programme en tant que service ou autrement dans une fenêtre de terminal réelle, ces messages peuvent être perdus, car il n'y a pas tty pour afficher les messages.
Voir mon article sur la redirection de libc pour écrire vers stderr au lieu de / dev / tty:
Attraper les messages d'erreur libc, rediriger depuis / dev / tty
Un cas où le processus obtient SIGABRT de lui-même: Hrvoje a mentionné qu'un virtuel pur enterré était appelé depuis ctor générant un abandon, j'ai recréé un exemple pour cela. Ici, lorsque d doit être construit, il appelle d'abord sa classe de base A ctor, et passe le pointeur intérieur à lui-même. A ctor appelle la méthode virtuelle pure avant que la table ne soit remplie avec un pointeur valide, car 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é
exécuter: ./aa
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
permet maintenant de voir rapidement le fichier core, et de valider que SIGABRT a bien été appelé:
gdb aa core
voir les règlements:
i r
rdx 0x6 6
rsi 0x69a 1690
rdi 0x69a 1690
rip 0x7feae3170c37
vérifier le code:
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
:)
Comme "@sarnold", comme il a été judicieusement souligné, tout processus peut envoyer un signal à tout autre processus, par conséquent, un processus peut envoyer SIGABORT à un autre processus et dans ce cas, le processus de réception est incapable de distinguer si sa venue en raison de sa propre modification de mémoire etc, ou quelqu'un d'autre a "unicastly", envoyez-le.
Dans l'un des systèmes sur lesquels j'ai travaillé, il y a un détecteur de blocage qui détecte réellement si le processus sort d'une tâche en faisant battre le cœur ou non. Sinon, il déclare que le processus est dans un état de blocage et lui envoie SIGABORT.
Je voulais juste partager cette perspective en référence à la question posée.
Je donnerai ma réponse du point de vue de la programmation compétitive (cp) , mais elle s'applique également à d'autres domaines.
Plusieurs fois en faisant du cp, les contraintes sont assez importantes.
Par exemple : j'avais une question avec une variable N, M, Q
telle que 1 ≤ N, M, Q < 10^5
.
L'erreur que je faisais était je déclarai un tableau 2D entier de taille 10000 x 10000
dans C++
et eu du mal avec l' SIGABRT
erreur à Codechef pendant presque 2 jours.
Maintenant, si nous calculons:
Taille typique d'un entier: 4 octets
Nombre de cellules dans notre réseau: 10000 x 10000
Taille totale (en octets): 400000000 octets = 4 * 10 ^ 8 ≈ 400 Mo
Vos solutions à ces questions fonctionneront sur votre PC (pas toujours) car il peut se permettre cette taille.
Mais les ressources des sites de codage (juges en ligne) sont limitées à quelques Ko.
Par conséquent, l' SIGABRT
erreur et d'autres erreurs de ce type.
Conclusion:
Dans de telles questions, nous ne devons pas déclarer un tableau ou un vecteur ou tout autre DS de cette taille, mais notre tâche est de rendre notre algorithme si efficace qu'il fonctionne sans eux (DS) ou avec moins de mémoire.
PS : Il peut y avoir d'autres raisons à cette erreur; ci-dessus était l'un d'eux.