Quand un processus reçoit-il SIGABRT (signal 6)?

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?

y a-t-il un moyen d'identifier le processus qui envoie ce signal?

150
demandé sur Shree 2010-08-05 13:00:18

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.

146
répondu Nordic Mainframe 2015-04-05 17:20:37

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) .

46
répondu sarnold 2010-08-05 09:06:24

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.

40
répondu IanH 2018-07-07 02:44:48

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.

13
répondu Mig 2011-10-07 16:57:33

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();
10
répondu Sudip Bhattarai 2016-03-10 08:17:20

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

5
répondu Mark Lakata 2017-05-23 11:55:09

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

:)

2
répondu Alexander Kruman 2017-03-29 08:20:11

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.

1
répondu anonymous 2017-06-12 15:47:02