284 votes

Quand un processus obtient-il SIGABRT (signal 6) ?

Quels sont les scénarios dans lesquels un processus reçoit un SIGABRT en C++ ? Ce signal provient-il toujours de l'intérieur 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 ?

7 votes

Il y a plusieurs façons de procéder. La plus simple, si vous avez écrit le programme, est d'enregistrer un gestionnaire de signal pour SIGABRT qui imprime cette information et vide ses flux avant de revenir. La deuxième façon la plus simple est d'exécuter le programme dans strace. Le troisième moyen le plus simple est de s'assurer que le programme génère un fichier core lorsqu'il se plante, et de le découvrir via le core dump.

9voto

Mark Lakata Points 3458

La libc de GNU imprimera l'information à /dev/tty concernant certaines conditions fatales avant d'appeler abort() (qui déclenche ensuite SIGABRT ), mais si vous exécutez votre programme comme un service ou autrement pas dans une vraie fenêtre de terminal, ces messages peuvent être perdus, parce qu'il n'y a pas de tty pour afficher les messages.

Voir mon post sur la redirection de libc pour écrire sur stderr au lieu de /dev/tty :

Récupération des messages d'erreur de libc, redirection depuis /dev/tty

5voto

Un cas où un processus reçoit SIGABRT de lui-même : Hrvoje a mentionné le fait qu'un virtual pur enterré appelé par un ctor génère un abort, j'ai recréé un exemple pour cela. Ici, quand d doit être construit, il appelle d'abord sa classe de base A ctor, et passe un pointeur intérieur à lui-même. le ctor A appelle une 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é

exécuter : ./aa

pure virtual method called
terminate called without an active exception
Aborted (core dumped)

Maintenant, voyons rapidement le fichier de base, et validons 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érifiez 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

)

2voto

anonymous Points 360

Dans mon cas, c'était dû à une entrée dans un tableau à un index égal à la longueur du tableau.

string x[5];

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

    cin>>x[i];

}

x[5] est accédé alors qu'il n'est pas présent.

1voto

Genius Points 1104

Je vais donner ma réponse à partir d'un programmation compétitive (pc) mais elle s'applique également à d'autres domaines.

Souvent, en faisant un cp, les contraintes sont assez grandes.

Par exemple : J'avais une question avec une variable N, M, Q tal que 1 ≤ N, M, Q < 10^5 .

L'erreur que j'ai commise était de déclarer un tableau d'entiers 2D de taille 10000 x 10000 en C++ et a lutté avec le SIGABRT erreur au Codechef depuis presque 2 jours.

Maintenant, si nous calculons :

Taille typique d'un entier : 4 octets

Nombre de cellules dans notre tableau : 10000 x 10000

Taille totale (en octets) : 400000000 octets = 4*10^8 ≈ 400 MB

Vos solutions à ces questions fonctionneront sur votre PC (pas toujours) car il peut supporter cette taille.

Mais les ressources des sites de codage (juges en ligne) sont limitées à quelques Ko.

Par conséquent, le SIGABRT et d'autres erreurs de ce type.

Conclusion :

Dans de telles questions, nous ne devrions 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 ; la raison ci-dessus en est une.

1voto

Fooo Points 419

Comme "@sarnold" l'a fait remarquer avec justesse, tout processus peut envoyer un signal à n'importe quel autre processus, donc un processus peut envoyer SIGABORT à un autre processus & dans ce cas, le processus récepteur est incapable de distinguer si cela vient de sa propre modification de la mémoire, etc. ou si quelqu'un d'autre lui a envoyé "unicastly".

Dans l'un des systèmes sur lesquels j'ai travaillé, il existe un détecteur de blocage qui détecte si le processus sort d'une tâche en donnant un battement de cœur ou non. Si ce n'est pas le cas, il déclare que le processus est en état de blocage et lui envoie SIGABORT.

Je voulais juste partager cette prospective en référence à la question posée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X