4
votes

Quelle est la différence entre SIGABRT et SIGSEGV

J'ai fait l'erreur de vidage de noyau avec les deux morceaux de codes ci-dessus:

//test.cpp
int main()
{
    int *p = new int;
    *p = 100;
    delete p;
    delete p;
    return 0;
}

//test2.cpp
int main()
{
    int *p = new int;
    *p = 100;
    delete p;
    *p = 111;
    std::cout<<*p<<std::endl;
    return 0;
}

Gdb m'a dit que le premier morceau de code avait été vidé à cause du signal SIGABRT, tandis que le deuxième morceau du code a été vidé à cause du signal SIGSEGV.

Pouvez-vous dire quelle est la différence?


5 commentaires

Voici une belle liste de ce que signifient les différents signaux: en.cppreference.com/w/c / program / SIG_types


Rien dans cette question n'est C. Veuillez faire plus attention en sélectionnant les balises dans les prochaines questions.


Les deux extraits ont un comportement indéfini et peuvent provoquer l'un de ces signaux, voire aucun. Alors ils ne démontrent rien


@VTT Avec une discussion sur pourquoi chacun est UB, ce serait une bonne réponse.


Une explication sur pourquoi chacun est UB peut être trouvée parmi les questions plus anciennes, et cela n'a rien à voir avec le titre de cette question.


3 Réponses :


2
votes

Ces deux exemples sont des comportements indéfinis , cela signifie que selon C ++, le compilateur (et le système) peuvent faire ce qu'il veut.

  • Dans le cas 1, il y a probablement une vérification de la double suppression d'un pointeur, donc SIGABRT est signalé. SIGABRT signifie condition de terminaison anormale, comme par exemple initiée par abort () .
  • Dans le cas 2, le système détecte votre respect d'un pointeur supprimé et crée un signal SIGSEGV . SIGSEGV signifie accès mémoire invalide (erreur de segmentation)

Mais les deux sont toujours UB, donc ce n'est qu'une fonctionnalité de votre compilateur / os / system actuel. La différence entre les erreurs ressort clairement de la définition des erreurs ici . L'un est un abandon, généralement généré par le compilateur ou le codeur. L'une est causée par un accès mémoire non valide, généralement signalé par le système d'exploitation ou le matériel.


2 commentaires

cela n'explique pas non plus la différence entre SIGABRT et SIGSEGV


@VTT Merci pour le tuyau.



2
votes

La suppression d'un pointeur deux fois est un comportement indéfini, ce qui signifie que tout peut arriver. Dans ce cas, le signal SIGABRT est émis.

Accéder à la mémoire qui n'appartient pas au programme est également un comportement non défini qui dans ce cas entraîne une erreur de segmentation et SIGSEGV est émis.

  • SIGABRT indique une erreur détectée par le programme lui-même et signalée en appelant abandonner .
  • SIGSEGV indique un accès non valide à une mémoire valide.

0 commentaires

4
votes

Le SIGABRT est explicitement détecté et signalé par l'implémentation de delete dont a détecté l'invalidité de la deuxième suppression. Il se lance en appelant la fonction abort

Le SIGSEGV est différent, il est en cours plutôt que détecté par un check dans une librairie comme le précédent, il se lance via la gestion mémoire de l'OS

voir https://en.cppreference.com/w/c/program/ SIG_types


5 commentaires

Je vois que vous avez copié le lien du premier commentaire, mais le reste de la réponse est juste une tentative d'expliquer UB


@VTT toute la différence dans le mode de détection


@VTT plutôt que de simplement critiquer s'il vous plaît mettez votre réponse pour nous permettre à tous d'apprendre ce qu'est une vraie réponse ;-)


@bruno La critique constructive est quelque chose de bien. Je crois que VTT essaie de vous aider avec votre réponse, pas de lui faire du mal ...


@FantasticMrFox oui, bien sûr, j'étais ironique. Mais faites vous-même attention de ne pas lui faire de mal en écrivant mal son nom, il est V TT pas C TT (c'est une blague, ne vous méprenez pas tous les deux ^^). Oh, vous avez corrigé