Qu'est-ce qu'un défaut de segmentation? Est-ce différent en C et C ++? Comment les défauts de segmentation et les pointeurs pendants sont-ils liés?
NullPointerException
.
Qu'est-ce qu'un défaut de segmentation? Est-ce différent en C et C ++? Comment les défauts de segmentation et les pointeurs pendants sont-ils liés?
NullPointerException
.
Réponses:
La faute 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'aide 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 qui a déjà été libérée, écrire dans une partie en lecture seule de la mémoire, etc. L'erreur de segmentation est essentiellement la même dans la plupart des langues qui vous permettent de jouer avec la gestion de la mémoire, il n'y a pas de différence principale entre les segfaults en C et C ++.
Il existe de nombreuses façons d'obtenir une erreur de segmentation, au moins dans les langages de niveau inférieur tels que C (++). Une façon courante d'obtenir un défaut de segmentation est de déréférencer un pointeur nul:
int *p = NULL;
*p = 1;
Une autre erreur de segmentation se produit lorsque vous essayez d'écrire sur une partie de la mémoire qui a été marquée 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
Le pointeur pendant fait pointer vers une chose qui n'existe plus, comme ici:
char *p = NULL;
{
char c;
p = &c;
}
// Now p is dangling
Le pointeur est p
suspendu car il pointe vers une variable de caractère c
qui a cessé d'exister après la fin du bloc. Et lorsque vous essayez de déréférencer un pointeur suspendu (comme *p='A'
), vous obtiendrez probablement un défaut de segmentation.
c
c'est local, cela signifie qu'il a été poussé sur la pile après {
et en est sorti après }
. le pointeur pendant n'est qu'une référence à un décalage qui est maintenant hors de la pile. c'est pourquoi le modifier dans un programme simple ne déclenchera jamais de défaut de segmentation. d'un autre côté, cela peut conduire à une erreur de segmentation dans un cas d'utilisation plus complexe, où d'autres appels de fonction peuvent entraîner la croissance de la pile et contenir les données pointées par le pointeur pendant. écrire sur ces données (vars locaux) entraînerait un comportement indéfini (segfault & Co)
SIGSEGV
, donc je ne m'attendrai pas à un tel signal en manipulant la pile.
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'accéder à un autre en utilisant une valeur de pointeur. Une exception à cela peut être les bibliothèques partagées qui sont le même espace d'adressage 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 chaque processus (pour éviter le vidage TLB sur syscall, je pense). 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 pouvons généralement y accéder (c’est pourquoi ils sont là,
Néanmoins, une erreur de segmentation peut se produire en cas d'accès incorrect à notre propre mémoire (de processus) (par exemple, en essayant d'écrire sur un espace non accessible en écriture). Mais la raison la plus courante en est l'accès à la partie de l'espace d'adressage virtuel qui n'est pas du tout mappée à un espace physique.
Et tout cela en ce qui concerne les systèmes de mémoire virtuelle.
Une erreur de segmentation est causée par une demande de page que le processus n'a pas répertoriée dans sa table de descripteurs ou par une demande non valide pour une page qu'il a répertoriée (par exemple, une demande d'écriture sur une page en lecture seule).
Un pointeur pendant est un pointeur qui peut ou non pointer vers une page valide, mais pointe vers un segment de mémoire "inattendu".
Pour être honnête, comme d'autres affiches l'ont mentionné, Wikipédia a un très bon article à ce sujet, alors lisez-le. Ce type d'erreur est très courant et s'appelle souvent 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 qui autorise les pointeurs. Ces types d'erreurs sont généralement causés par des pointeurs qui sont
Selon wikipedia:
Une erreur de segmentation se produit lorsqu'un programme tente d'accéder à un emplacement mémoire auquel il n'est pas autorisé à accéder, ou tente d'accéder à un emplacement mémoire d'une manière non autorisée (par exemple, en tentant d'écrire dans un emplacement en lecture seule, ou pour remplacer une partie du système d'exploitation).
Le défaut de segmentation est également provoqué 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, peut-être qu'un memtest pourrait vous aider.
La solution dans ce cas, changez la RAM.
Éditer:
Voici une référence: défaut de segmentation par matériel
Une erreur de segmentation se produit lorsqu'un processus (instance en cours d'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 inexistante (non valide). Un problème de référence pendante (pointeur) signifie qu'essayer 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
La page Segmentation_fault de Wikipédia a une très belle description à ce sujet, soulignant simplement les causes et les raisons. Jetez un œil au wiki pour une description détaillée.
En informatique, une erreur de segmentation (souvent raccourcie en erreur de segmentation) ou une violation d'accès est une erreur déclenchée par un matériel avec protection de la mémoire, informant un système d'exploitation (OS) d'une violation d'accès à la mémoire.
Voici quelques causes typiques d'un défaut de segmentation:
Ceux-ci à leur tour sont souvent causés par des erreurs de programmation qui entraînent un accès à la mémoire non valide:
Déréférencement ou affectation à un pointeur non initialisé (pointeur sauvage, qui pointe vers une adresse mémoire aléatoire)
Déréférencement ou affectation à un pointeur libéré (pointeur suspendu, 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 se compile pas correctement. (Certains compilateurs afficheront un fichier exécutable malgré la présence d'erreurs de compilation.)
En termes simples: une erreur de segmentation est le système d'exploitation envoyant un signal au programme disant qu'il a détecté un accès illégal à la mémoire et qu'il met fin prématurément au programme pour éviter que la mémoire ne soit corrompue.
"Erreur de segmentation" signifie que vous avez essayé d'accéder à une mémoire à laquelle vous n'avez pas accès.
Le premier problème concerne vos arguments de main. La fonction principale devrait être int main(int argc, char *argv[])
, et vous devriez vérifier que argc est au moins 2 avant d'accéder à argv [1].
De plus, puisque vous passez un flottant à printf (qui, soit dit en passant, est converti en double lors du passage à printf), vous devez utiliser le spécificateur de format% f. Le spécificateur de format% s est pour les chaînes (tableaux de caractères terminés par '\ 0').
Une erreur de segmentation ou une violation d'accès se produit lorsqu'un programme tente d'accéder à un emplacement mémoire qui n'existe pas ou tente d'accéder à un emplacement mémoire d'une manière non 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 une erreur de segmentation se produit.
Causes de 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).
Il y a plusieurs bonnes explications de la "faute de segmentation" dans les réponses, mais comme avec la faute de segmentation il y a souvent un vidage du contenu de la mémoire, je voulais partager où la relation entre la partie "vidage de mémoire" dans la faute de segmentation (vidage de mémoire ) et la mémoire vient de:
D'environ 1955 à 1975 - avant la mémoire des semi-conducteurs - la technologie dominante dans la mémoire des ordinateurs utilisait de minuscules beignets magnétiques enfilés sur des fils de cuivre. Les beignets étaient connus sous le nom de "noyaux de ferrite" et la mémoire principale ainsi connue sous le nom de "mémoire centrale" ou "noyau".
Pris d' ici .
Il y a suffisamment de définitions de défaut de segmentation, je voudrais citer quelques exemples que j'ai rencontrés lors de la programmation, qui peuvent sembler des erreurs stupides, mais qui perdront beaucoup de temps.
vous pouvez obtenir un défaut de segmentation dans le cas ci-dessous pendant une incompatibilité de type argumet dans printf
#include<stdio.h>
int main(){
int a = 5;
printf("%s",a);
return 0;
}
production : Segmentation Fault (SIGSEGV)
lorsque vous avez oublié d'allouer de la mémoire à un pointeur, mais que vous essayez de l'utiliser.
#include<stdio.h>
typedef struct{
int a;
}myStruct;
int main(){
myStruct *s;
/* few lines of code */
s->a = 5;
return 0;
}
production : Segmentation Fault (SIGSEGV)
Le sens simple de Segmentation fault
est que vous essayez d'accéder à une mémoire qui ne vous appartient pas. Segmentation fault
se produit lorsque nous tentons de lire et / ou d'écrire des tâches dans un emplacement mémoire en lecture seule ou d'essayer de libérer de la mémoire. En d'autres termes, nous pouvons expliquer cela comme une sorte de corruption de mémoire.
Ci-dessous, je mentionne les erreurs courantes commises par les programmeurs qui conduisent à Segmentation fault
.
scanf()
dans le mauvais sens (oublié de mettre &
).int num;
scanf("%d", num);// must use &num instead of num
int *num;
printf("%d",*num); //*num should be correct as num only
//Unless You can use *num but you have to point this pointer to valid memory address before accessing it.
char *str;
//Stored in read only part of data segment
str = "GfG";
//Problem: trying to modify read only memory
*(str+1) = 'n';
// allocating memory to num
int* num = malloc(8);
*num = 100;
// de-allocated the space allocated to num
free(num);
// num is already freed there for it cause segmentation fault
*num = 110;
printf()
et scanf()
'