Question Qu'est-ce qu'un défaut de segmentation?


Qu'est-ce qu'un défaut de segmentation? Est-ce différent en C et C ++? Comment sont liés les défauts de segmentation et les pointeurs pendants?


440
2018-02-27 09:23


origine


Réponses:


L'erreur de segmentation est un type spécifique d'erreur causée par l'accès à la mémoire qui "ne vous appartient pas". C'est un mécanisme d'assistance qui vous empêche de corrompre la mémoire et d'introduire des bogues de mémoire difficiles à déboguer. Chaque fois que vous obtenez une erreur de segmentation, vous savez que vous faites quelque chose de mal avec la mémoire: accéder à une variable déjà libérée, écrire dans une partie de la mémoire, etc. La faute de segmentation est essentiellement la même dans la plupart des langues. la gestion de la mémoire, il n'y a pas de différence principale entre les segfaults en C et C ++.

Il existe plusieurs façons d'obtenir une erreur de segmentation, au moins dans les langages de bas niveau tels que C (++). Une façon courante d'obtenir un segfault est de déréférencer un pointeur nul:

int *p = NULL;
*p = 1;

Une autre erreur se produit lorsque vous essayez d'écrire sur une partie de la mémoire marquée comme étant en lecture seule:

char *str = "Foo"; // Compiler marks the constant string as read-only
*str = 'b'; // Which means this is illegal and results in a segfault

Pointeur pointant pointe vers une chose qui n'existe plus, comme ici:

char *p = NULL;
{
    char c;
    p = &c;
}
// Now p is dangling

Le pointeur p se balance parce qu'il pointe vers une variable de caractère c qui a cessé d'exister après la fin du bloc. Et quand vous essayez de déréférencer pointeur pointant (comme *p='A'), vous obtiendrez probablement un segfault.


535
2018-02-27 09:36



Il convient de noter que la faute de segmentation n'est pas causée par l'accès direct à une autre mémoire de processus (c'est ce que j'entends parfois), car ce n'est tout simplement pas possible. Avec la mémoire virtuelle, chaque processus a son propre espace d'adressage virtuel et il n'y a aucun moyen d'en accéder un autre en utilisant n'importe quelle valeur de pointeur. Les librairies partagées qui sont le même espace d'adresse physique mappé à (éventuellement) différentes adresses virtuelles et la mémoire du noyau qui est même mappée de la même manière dans tous les processus (pour éviter le vidage TLB sur syscall, je pense) peuvent être exceptionnelles. Et des choses comme shmat;) - c'est ce que je considère comme un accès "indirect". On peut, cependant, vérifier qu'ils sont généralement situés loin du code de processus et que nous sommes généralement en mesure d'y accéder (c'est pourquoi ils sont là, néanmoins leur accès de manière incorrecte produira une erreur de segmentation).

Cependant, une erreur de segmentation peut se produire en cas d'accès incorrect à notre propre mémoire (processus) (par exemple en essayant d'écrire dans un espace non-inscriptible). Mais la raison la plus courante est l'accès à la partie de l'espace d'adressage virtuel qui est non cartographié à un physique du tout.

Et tout cela en ce qui concerne les systèmes de mémoire virtuelle.


90
2017-07-03 23:22



Une erreur de segmentation est provoquée par une requête pour une page que le processus n'a pas répertoriée dans sa table descripteur ou une requête non valide pour une page répertoriée (par exemple, une demande d'écriture sur une page en lecture seule).

Un pointeur suspendu est un pointeur qui peut ou non pointer vers une page valide, mais pointe vers un segment de mémoire "inattendu".


27
2018-02-27 09:27



Pour être honnête, comme d'autres affiches l'ont mentionné, Wikipédia a un très bon article sur ce sujet alors jetez un oeil là-bas. Ce type d'erreur est très commun et souvent appelé d'autres choses telles que la violation d'accès ou la défaillance de protection générale.

Ils ne sont pas différents en C, C ++ ou tout autre langage permettant les pointeurs. Ces types d'erreurs sont généralement causés par des pointeurs qui sont

  1. Utilisé avant d'être correctement initialisé
  2. Utilisé après que la mémoire vers laquelle ils pointent a été réaffectée ou supprimée.
  3. Utilisé dans un tableau indexé où l'index est en dehors des limites du tableau. C'est généralement seulement lorsque vous faites du calcul de pointeur sur des tableaux traditionnels ou des chaînes c, et non sur des collections basées sur STL / Boost (en C ++).

24
2018-02-27 20:35



Tandis que la réponse de Zoul explique ce qu'est une faute de segmentation, j'ai trouvé que ce genre de bugs peut être particulièrement difficile à attraper, surtout si vous êtes nouveau dans des langages de bas niveau comme C ++ ou C. Voici quelques-unes des façons courantes d'obtenir erreur de segmentation dans votre programme:

Chaîne de contrôle de format incorrecte dans printf ou scanf déclarations

La chaîne de contrôle du format doit avoir le même nombre de spécificateurs de conversion (%s, %d etc.) printf ou scanf a des arguments à imprimer ou à lire. La même chose vaut pour fprintf et fscanf.

N'utilise pas & sur les arguments à scanf

Fonction scanf prend comme arguments la chaîne de contrôle de format et les adresses des variables dans lesquelles il placera les données dans lesquelles il lit. & L'opérateur (adresse de) est utilisé pour fournir l'adresse d'une variable.

Références de tableau hors-limites

Assurez-vous que vous n'avez pas violé les limites de tout tableau que vous utilisez; c'est-à-dire que vous n'avez pas indexé le tableau avec une valeur inférieure à l'indice de son élément le plus bas ou supérieure à l'indice de son élément le plus élevé. Valgrind peut être utile pour détecter de telles références - vous pouvez utiliser valgrind avec le --tool=exp-sgcheck drapeau.

Accès aux pointeurs non initialisés

Une variable de pointeur doit recevoir une adresse valide avant d'être accessible. Assurez-vous que vous avez initialisé tous les pointeurs pour pointer vers une zone de mémoire valide.

Utilisation incorrecte du & (adresse de) et * opérateurs (déréférencés)

Vous devrez faire attention en les utilisant, en particulier en passant des paramètres par référence / en utilisant des pointeurs.

Limites Shell

Parfois, les erreurs de segmentation ne sont pas causées par des bogues dans le programme mais sont causées à la place par des limites de mémoire système trop faibles. Habituellement, c'est la limite sur la taille de la pile qui cause ce genre de problème (débordements de pile). Pour vérifier les limites de la mémoire, utilisez le ulimit commande dans bash.

Déboguer en utilisant gdb

Vous pouvez utiliser le débogueur gdb pour voir la trace de la core fichier déposé par votre programme. Chaque fois que les programmes segfault, ils jettent généralement le contenu de la mémoire au moment de l'accident dans un core fichier (core dumped). Compilez votre programme avec le -g drapeau, courir dans gdb et utilise bt (backtrace).


18
2018-01-10 15:58



Selon wikipedia:

Une erreur de segmentation se produit lorsqu'un   programme tente d'accéder à une mémoire   emplacement qu'il n'est pas autorisé à   accès ou tente d'accéder à une mémoire   emplacement d'une manière qui n'est pas autorisée   (par exemple, essayer d'écrire sur un   emplacement en lecture seule ou pour écraser   partie du système d'exploitation).


14
2018-02-27 09:30



Erreur de segmentation est également causé par des pannes matérielles, dans ce cas les mémoires RAM. C'est la cause la moins fréquente, mais si vous ne trouvez pas d'erreur dans votre code, un mémtest pourrait peut-être vous aider.

La solution dans ce cas, changer la RAM.

modifier:

Ici il y a une référence: Défaut de segmentation par matériel


10
2018-06-24 16:59



Erreur de segmentation se produit lorsqu'un processus (exécution d'un programme) tente d'accéder à l'adresse mémoire en lecture seule ou à la plage de mémoire utilisée par un autre processus ou d'accéder à l'adresse mémoire non valide (non valide). Problème de référence (pointeur) signifie que vous essayez d'accéder à un objet ou une variable dont le contenu a déjà été supprimé de la mémoire, par exemple:

int *arr = new int[20];
delete arr;
cout<<arr[1];  //dangling problem occurs here

6
2017-12-10 22:34



Wikipédia Segmentation_fault La page a une très belle description à ce sujet, soulignant simplement les causes et les raisons. Jetez un oeil dans le wiki pour une description détaillée.

En informatique, une erreur de segmentation (souvent raccourcie à segfault) ou une violation d'accès est une erreur soulevée par le matériel avec protection de la mémoire, notifiant un système d'exploitation (OS) à propos d'une violation d'accès à la mémoire.

Voici quelques causes typiques d'une erreur de segmentation:

  • Déréférencement des pointeurs NULL - ceci est spécial-cased par le matériel de gestion de mémoire
  • Tentative d'accès à une adresse mémoire inexistante (en dehors de l'espace d'adressage du processus)
  • Tentative d'accès à la mémoire, le programme n'a pas les droits (tels que les structures de noyau dans le contexte de processus)
  • Tentative d'écriture de mémoire en lecture seule (par exemple, segment de code)

Celles-ci sont souvent causées par des erreurs de programmation qui entraînent un accès mémoire invalide:

  • Déréférencement ou affectation à un pointeur non initialisé (pointeur sauvage, pointant vers une adresse mémoire aléatoire)

  • Déréférencement ou assignation à un pointeur libéré (pointeur qui pointe vers la mémoire qui a été libérée / désallouée / supprimée)

  • Un débordement de tampon.

  • Un débordement de pile.

  • Tentative d'exécution d'un programme qui ne compile pas correctement. (Certains compilateurs afficheront un fichier exécutable malgré la présence d'erreurs de compilation.)


4
2017-10-14 10:05



En termes simples: erreur de segmentation est le système d'exploitation qui envoie un signal au programme disant qu'il a détecté un accès mémoire illégal et met prématurément fin au programme pour prévenir la mémoire d'être corrompu.


3
2017-07-19 13:43



Une violation de segmentation ou d'accès se produit lorsqu'un programme tente d'accéder à un emplacement de mémoire qui n'existe pas ou tente d'accéder à un emplacement de mémoire d'une manière qui n'est pas autorisée.

 /* "Array out of bounds" error 
   valid indices for array foo
   are 0, 1, ... 999 */
   int foo[1000];
   for (int i = 0; i <= 1000 ; i++) 
   foo[i] = i;

Ici, je [1000] n'existe pas, donc segfault se produit.

Causes du défaut de segmentation:

it arise primarily due to errors in use of pointers for virtual memory addressing, particularly illegal access.

De-referencing NULL pointers – this is special-cased by memory management hardware.

Attempting to access a nonexistent memory address (outside process’s address space).

Attempting to access memory the program does not have rights to (such as kernel structures in process context).

Attempting to write read-only memory (such as code segment).

0
2017-12-08 16:14