web-dev-qa-db-fra.com

Pourquoi une faute de segmentation n'est-elle pas récupérable?

Suivant ne question précédente de la mine , la plupart des commentaires disent: "N'ajoutez tout simplement pas, vous êtes dans un état de limbe, vous devez tout tuer et recommencer". Il y a aussi une solution de contournement "Safeish" .

Ce que je manque de comprendre, c'est Pourquoi Un défaut de segmentation est intrinsèquement non recouvertable.

Le moment où écrire à la mémoire protégée est capturé - sinon, le SIGSEGV ne serait pas envoyé.

Si le moment d'écrire à la mémoire protégée peut être attrapé, je ne vois pas pourquoi - en théorie - il ne peut pas être retourné, à un niveau bas et que SIGSEGV convertit une exception logicielle standard.

Veuillez expliquer pourquoi après une défaillance de segmentation, le programme est dans un état indéterminé, comme très évidemment, la défaillance est lancée Avant La mémoire était effectivement modifiée (je me trompe probablement et ne vois probablement pas pourquoi). S'il avait été lancé après, on pourrait créer un programme qui change de mémoire protégée, un octet à une époque, d'obtenir des défauts de segmentation et de reprogrammer finalement le noyau - un risque de sécurité qui n'est pas présent, comme nous le voyons toujours du monde.

  1. Quand exactement une défaillance de segmentation se produit (= quand est SIGSEGV envoyer)?
  2. Pourquoi le processus est-il dans un état de comportement non défini après ce point?
  3. Pourquoi n'est-ce pas recouvrable?
  4. Pourquoi - cette solution Évitez cet état irrécupérable? Est-ce même?
68
Gulzar

Votre programme est un état obsolète car c ne peut pas définir l'état. Les bugs qui provoquent ces erreurs sont un comportement indéfini. C'est la classe la plus nitaire de mauvais comportements.

Le problème clé avec la récupération de ces choses est que, en tant que comportement indéfini, le complicateur n'est pas obligé de les soutenir de quelque manière que ce soit. En particulier, cela peut avoir fait des optimisations qui, si seulement les comportements définis se produisent, ont pratiquement le même effet. Le compilateur est entièrement dans ses droits de réorganiser des lignes, de sauter des lignes et de faire toutes sortes de tours de fantaisie pour que votre code soit exécuté plus rapidement. Tout ce qu'il faut faire est de prouver que l'effet est identique selon le modèle de machine virtuelle C++.

Lorsqu'un comportement non défini se produit, tout ce qui sort de la fenêtre. Vous pouvez entrer dans des situations difficiles dans lesquelles le compilateur a des opérations réorganisées et maintenant ne peut pas Vous permet de vous rendre à un état que vous pourriez arriver en exécutant votre programme pendant une période de temps. N'oubliez pas que les affectations effacent l'ancienne valeur. Si une affectation a été déplacée avant la ligne qui segfaulée, vous ne pouvez pas récupérer l'ancienne valeur pour "dérouler" l'optimisation.

Le comportement de ce code de réorganisation a été identique à l'original, tant qu'aucun comportement non défini n'est survenu . Une fois le comportement non défini survenu, il expose le fait que la réordonnée s'est produite et pourrait modifier les résultats.

Le compromis ici est une vitesse. Étant donné que le compilateur ne marche pas sur des coquilles d'oeufs, terrifiait d'un comportement non spécifié du système d'exploitation, il peut faire un meilleur travail d'optimisation de votre code.

Maintenant, parce que le comportement non défini est toujours un comportement non défini, peu importe la quantité que vous le souhaitez, il ne peut pas y avoir de manière spécifique C++ pour gérer ce cas. La langue C++ ne peut jamais introduire un moyen de résoudre ce problème, du moins à faire du comportement défini et de payer les coûts pour cela. Sur une plate-forme donnée et un compilateur, vous pourrez peut-être identifier que ce compilit indéfini est en fait défini par votre compilateur, généralement sous la forme d'extensions. En effet, la réponse que j'ai liée précédemment montre un moyen de transformer un signal en une exception, qui fonctionne effectivement sur au moins une plate-forme/paire de compilateur.

Mais il doit toujours être sur la frange comme celle-ci. Les développeurs C++ valorisent la vitesse du code optimisé sur la définition de ce comportement non défini.

1
Cort Ammon

Il est absolument possible, mais cela dupliquerait des fonctionnalités existantes de manière moins stable.

Le noyau recevra déjà une exception de défaillance de la page lorsqu'un programme accède à une adresse qui n'est pas encore soutenue par la mémoire physique et affectera et éventuellement initialiser une page en fonction des mappages existants, puis réessayez l'instruction incriminée.

Un gestionnaire de SEGV hypothétique ferait exactement la même chose: décider de ce qui devrait être mappé à cette adresse, créer la cartographie et réessayer l'instruction - mais avec la différence que si le gestionnaire entraînerait un autre SEGV, nous pourrions aller dans une boucle sans fin ici et la détection serait difficile car cette décision devrait examiner le code - afin de créer un problème d'arrêt ici.

Le noyau alloue déjà des pages de mémoire paresseusement, permet de mapper et de prendre en charge des mappages partagés avec une sémantique de copie-on-écriture, il n'ya donc pas grand chose à gagner de ce mécanisme.

0
Simon Richter

Votre programme ne peut pas récupérer d'une faute de segmentation car elle n'a aucune idée de l'étatn'importe quoiest dans.

Considérez cette analogie.

Vous avez une belle maison au Maine avec un joli jardin avant et un sentier de pierres en marche à travers dessus. Pour une raison quelconque, vous avez choisi de connecter chaque pierre à la suivante avec un ruban (A.K.A. Vous les avez fabriquées dans une liste individuellement liée).
Un matin, sortant de la maison, vous appuyez sur la première pierre, puis suivez le ruban vers la seconde, puis à nouveau au troisième, mais lorsque vous marchez sur leQuatrièmeStone, vous vous trouvez soudainement à Albuquerque.

Maintenant, dites-nous - commentvous récupérer de__?

Votre programme a le même dilatéral.
[.____] Quelque chose alléspectaculairefaux mais votre programme aaucune idéece qu'il était fait ou comment/commentdoquelque chose d'utile à ce sujet.
[.____] Par conséquent: il se bloque et brûle.

0
Phill W.