8
votes

Comment exactement une exception de violation d'accès est déclenchée?

Parfois, les bugs peuvent causer une exception de violation d'accès à la mémoire.

Comment exactement cette exception est déclenchée? Quel mécanisme fonctionne derrière les scènes?

a-t-il besoin de supporter de la CPU (à partir de ce que la CPU?) / Du système d'exploitation (à partir de quelle version?) / Du compilateur (à partir de quelle version?)

Edit:

Un scénario spécifique Je souhaite mieux comprendre:

Le code suivant peut entraîner une exception d'une violation d'accès. < / p> xxx

Je suppose que czxxx pointe sur un bloc de mémoire en lecture seule, mais ce qui se passe exactement?


0 commentaires

6 Réponses :


0
votes
void Kaboom()
{
    int* certain_death = NULL;
    *certain_death = 0;
}

1 commentaires

En fait, votre exemple a un comportement indéfini en fonction de la norme;)



7
votes

Dans l'architecture X86 (et la plupart des autres aussi), ceci est démarré à partir de la MMU - l'unité de gestion de la mémoire. Le MMU est utilisé pour traduire des adresses de mémoire virtuelles aux adresses de mémoire physique. Si une demande est faite pour accéder à une adresse non valide (0x00000000 ou quelque chose de trop élevé), le MMU piégera (interruption) au système d'exploitation (ceci est fait pour chaque accès non dans la TLB (Traduire le tampon de lookaside - le cache de traduction MMU. "))). Ici, le système d'exploitation sera en mesure de dire qu'il s'agit d'un accès illégal de la mémoire et de se propager à l'application utilisateur via le mécanisme dépendant du système d'exploitation (signaux de Linux (SIGSEGV), je ne connais pas assez de Windows pour dire comment cela se fait en elle).

Cette fonctionnalité est disponible pour tout CPU, système d'exploitation et compilateur moderne. L'exigence la plus élémentaire est une MMU, qui est présente dans tous les processeurs intégrés les plus fondamentaux. Je doute que tout PC fonctionne actuellement qui ne supporte pas cela.

EDIT:

Après la méthode OP, lorsqu'une chaîne littérale est utilisée, la mémoire est placée dans le segment .Text de l'exécutable. C'est là que le code binaire et les valeurs constants sont assis. Naturellement, dans la plupart des OSS, ceci est en lecture seule (en particulier sous Linux avec diverses améliorations de sécurité). Lorsque vous essayez de changer une valeur d'une chaîne littérale, vous essayez essentiellement d'écrire à une mémoire en lecture seule, ce qui entraîne une violation d'accès. Encore une fois, cela est capturé par le MMU qui voit une commande d'écriture à une adresse mémoire en lecture seule.


1 commentaires

Le mécanisme dépendant du système d'exploitation est appelé "exceptions structurées" sous Windows: msdn.microsoft.com/en-us/library/ms680657%28v=vs.85%29.aspx



2
votes

Lorsque vous essayez d'accéder à une adresse mémoire, l'ordinateur passe à travers plusieurs étapes:

  • Si l'adresse fait partie du segment de mémoire actuelle, l'accès est accordé.
  • Sinon, si le segment de l'adresse est en mémoire avec une autorisation d'accès appropriée , l'accès est accordé.

    Si l'adresse n'est pas en mémoire, la CPU générera une exception de vérification de la mémoire. À ce stade, le système d'exploitation prend la relève.

    • Si le segment est disponible en mémoire virtuelle avec une autorisation d'accès appropriée , elle est chargée dans la mémoire et attribuée au gestionnaire de mémoire virtuelle; l'accès est ensuite accordé.

      Si, à ce stade, la mémoire n'est pas disponible, il existe une des deux possibilités. L'adresse n'est pas disponible, soit vous n'avez pas les autorisations dont vous avez besoin (par exemple, essayer d'écrire en mémoire en lecture seule). Dans ce cas, le système d'exploitation passera la violation d'accès au processus.

      Quant aux versions CPU et OS, il s'agit d'un système qui permet une mémoire virtuelle. Je ne connais pas les détails de cela.


0 commentaires

12
votes

Les violations d'accès à la mémoire sont un gros sujet :)

Protection des informations dans les systèmes informatiques (à partir de 1973 :) établie d'un mécanisme de segments , où les processus sont attribués à une base et a lié ​​; Toute tentative d'accès à la mémoire en dehors de la plage base: base + liaison signifiait que le programme avait fait quelque chose de stupide et doit être tué.

La ligne de processeurs 80x86 implémente le support de segment de base et le Gemsos Security Le noyau est un noyau de système d'exploitation certifié A1 basé sur ce mécanisme.

Mais les segments ne sont pas très dynamiques, et presque tous les systèmes d'exploitation modernes sont Systèmes de pagination , que page dans la mémoire quand il n'est pas disponible. Ceci repose sur la CPU ayant un MMU , unité de gestion de la mémoire, qui vérifie tous les accès à la mémoire pour les privilèges corrects et présence / absence du mappage de mémoire correct. Lorsqu'un processus tente d'accéder à la mémoire qui n'est pas actuellement mappé dans la RAM, le MMU signale la CPU selon laquelle une erreur est survenue et que la CPU suspend le processus de chargement de la page de mémoire demandée à partir du disque. (Ou si la mémoire ne doit pas être mappée pour le processus, disons qu'il tente d'accéder à 0x0 ou à un emplacement de mémoire aléatoire qui n'a pas été mappé avec MMAP ou mémoire similaire alloué des primitives, il tue le processus.)

80386 Intel a été la première puce Intel à supporter la pagination, laquelle est la raison pour laquelle Windows 3.1's "386 enchante enchanté" était donc beaucoup mieux que le mode 286.

Les compilateurs ne sont pas vraiment impliqués, mais la CPU, le MMU et le système d'exploitation du noyau doivent tous travaillent ensemble.


2 commentaires

Et si la RAM et le disque sont-ils tous les deux?


@Scott 混合 理论 Il est normal que la RAM soit pleine ou très presque entièrement inutilisée, la RAM est gaspillée. Étant donné que la performance se dégrade, plus l'ordinateur doit utiliser l'espace d'échange, normalement, les gens essaieront de ne exécuter que autant de logiciels que vous intégrerez en mémoire. Une fois que l'espace de swap est plein, le noyau commencera à renvoyer des erreurs pour des allocations de mémoire ou tuera des processus entiers pour libérer de l'espace. Recherchez "Oom Killer" pour plus de détails à ce sujet.



1
votes

La violation de l'accès à la mémoire peut se produire ici également:

delete pSample;

//again deleting the same memory!
delete pSample;


0 commentaires

2
votes

Toutes ces réponses expliquent très bien ce qui se passe très bien au niveau du processeur. Comme mentionné, une fois que le processeur a souligné une interruption au système d'exploitation, les éléments changent avec différents systèmes d'exploitation.

Windows utilise un mécanisme appelé " exceptions structurées ". Très important de ne pas confondre cela avec des exceptions C ++, elles sont différentes. Exceptions structurées conceptuellement forts> fonctionne de la même manière que c ++ exceptions, en ce sens qu'ils détournent la pile à la recherche d'un gestionnaire. Les exceptions structurées étant agnostiques linguistiques, elles font pas forts> destructeurs d'appel ou font un nettoyage. P>

Des exceptions structurées peuvent être capturées avec P>

__try
{
  //Usual code
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
  //Handling code
}
__finally
{
  //Cleanup
}


0 commentaires