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?
3 Réponses :
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.
SIGABRT
est signalé. SIGABRT
signifie condition de terminaison anormale, comme par exemple initiée par abort () . 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.
cela n'explique pas non plus la différence entre SIGABRT et SIGSEGV
@VTT Merci pour le tuyau.
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. 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
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 ^^).
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.