logo

Erreur de segmentation en C/C++

Défauts de segmentation en C ou C++ est une erreur qui se produit lorsqu'un programme tente d'accéder à un emplacement mémoire auquel il n'est pas autorisé à accéder. Généralement, cette erreur se produit lorsque l’accès à la mémoire est violé et constitue un type de défaut de protection général. Défauts de segmentation sont l'abréviation de défauts de segmentation.

Le vidage de mémoire fait référence à l'enregistrement de l'état du programme, c'est à dire de ses ressources en mémoire et en processeur. Essayer d'accéder à une mémoire inexistante ou à une mémoire utilisée par d'autres processus provoque également une erreur de segmentation qui conduit à un vidage mémoire.



Un programme a accès à des régions spécifiques de la mémoire pendant son exécution. Premièrement, la pile est utilisée pour contenir les variables locales de chaque fonction. De plus, il peut avoir de la mémoire allouée au moment de l'exécution et enregistrée sur le tas (nouveau en C++ et vous pouvez également l'entendre appelé le magasin gratuit ). La seule mémoire à laquelle le programme est autorisé à accéder est la sienne (la mémoire mentionnée précédemment). Une erreur de segmentation résultera de tout accès en dehors de cette région.

L'erreur de segmentation est un type spécifique d'erreur provoquée par l'accès à la mémoire qui ne t'appartient pas :

  • Lorsqu'un morceau de code tente d'effectuer une opération de lecture et d'écriture dans un emplacement en lecture seule de la mémoire ou dans un bloc de mémoire libéré, on parle d'erreur de segmentation.
  • Il s'agit d'une erreur indiquant une corruption de la mémoire.

Scénarios courants de défauts de segmentation

Lors d'une erreur de segmentation, un programme tente d'accéder à une mémoire qui n'est pas autorisée à accéder ou qui n'existe pas. Certains scénarios courants pouvant provoquer des erreurs de segmentation sont :



  1. Modifier une chaîne littérale
  2. Accéder à une adresse libérée
  3. Accès aux limites d'index hors tableau
  4. Mauvaise utilisation de scanf()
  5. Débordement de pile
  6. Déréférencement d'un pointeur non initialisé

1. Modification d'un littéral de chaîne

Les chaînes littérales sont stockées dans la section en lecture seule de la mémoire. C'est pourquoi le programme ci-dessous peut planter (donne une erreur de segmentation) car la ligne *(str+1) = 'n' tente d'écrire une mémoire en lecture seule.

Exemple:

C






// C program to demonstrate segmentation fault> // by modifying a string literal> #include> int> main()> {> >char>* str;> >// Stored in read only part of data segment //> >str =>'GfG'>;> >// Problem: trying to modify read only memory //> >*(str + 1) =>'n'>;> >return> 0;> }>

>

>

C++




// C++ program to demonstrate segmentation fault> // by modifying a string literal> #include> using> namespace> std;> int> main()> {> >char>* str;> >// Stored in read only part of data segment //> >str =>'GfG'>;> >// Problem: trying to modify read only memory //> >*(str + 1) =>'n'>;> >return> 0;> }>

>

>

Sortir

timeout : la commande surveillée a vidé le noyau

/bin/bash : ligne 1 : 32 Délai d'expiration de défaut de segmentation 15 s ./83b16132-8565-4cb1-aedb-4eb593442235 <83b16132-8565-4cb1-aedb-4eb593442235.in

Reportez-vous à Stockage des chaînes en C pour plus de détails.

2. Accéder à une adresse libérée

Ici, dans le code ci-dessous, le pointeur p est déréférencé après avoir libéré le bloc mémoire, ce qui n'est pas autorisé par le compilateur. De tels pointeurs sont appelés pointeurs suspendus et produisent des erreurs de segment ou une fin anormale du programme au moment de l'exécution.

Exemple:

C




// C program to demonstrate segmentation fault> // by Accessing an address that is freed> #include> #include> int> main(>void>)> {> >// allocating memory to p> >int>* p = (>int>*)>malloc>(8);> >*p = 100;> >// deallocated the space allocated to p> >free>(p);> >// core dump/segmentation fault> >// as now this statement is illegal> >*p = 110;> >printf>(>'%d'>, *p);> >return> 0;> }>

carte vs ensemble

>

>

C++




// C++ program to demonstrate segmentation fault> // by Accessing an address that is freed> #include> using> namespace> std;> int> main(>void>)> {> >// allocating memory to p> >int>* p = (>int>*)>malloc>(>sizeof>(>int>));> >*p = 100;> >// deallocated the space allocated to p> >free>(p);> >// segmentation fault> >// as now this statement is illegal> >*p = 110;> >return> 0;> }>

>

>

Sortir

Segmentation Fault>

3. Accès à l'index de tableau hors limites

En C et C++, l'accès à un index de tableau hors limites peut provoquer une erreur de segmentation ou un autre comportement non défini. Il n'y a pas de vérification des limites pour les tableaux en C et C++. Bien qu'en C++, l'utilisation de conteneurs tels qu'avec la méthode std::vector::at() ou avec une instruction if() peut empêcher les erreurs hors limites.

Exemple:

C




// C program to demonstrate segmentation> // fault when array out of bound is accessed.> #include> int> main(>void>)> {> >int> arr[2];> >// Accessing out of bound> >arr[3] = 10;> >return> (0);> }>

>

>

C++




// C++ program to demonstrate segmentation> // fault when array out of bound is accessed.> #include> using> namespace> std;> int> main()> {> >int> arr[2];> >// Accessing out of bound> >arr[3] = 10;> >return> 0;> }>

>

>

Sortir

Segmentation Faults>

4. Mauvaise utilisation de scanf()

La fonction scanf() attend l'adresse d'une variable en entrée. Ici, dans ce programme, n prend la valeur 2 et suppose que son adresse est 1000. Si nous passons n à scanf(), l'entrée extraite de STDIN est placée dans la mémoire invalide 2 qui devrait plutôt être 1000. Cela provoque une corruption de la mémoire conduisant à une erreur de segmentation.

Exemple:

C




// C program to demonstrate segmentation> // fault when value is passed to scanf> #include> int> main()> {> >int> n = 2;> >scanf>(>'%d'>, n);> >return> 0;> }>

>

>

C++

essayez le bloc catch en java




// C++ program to demonstrate segmentation> // fault when value is passed to scanf> #include> using> namespace> std;> int> main()> {> >int> n = 2;> >cin>>n;> >return> 0;> }>

>

>

Sortir

Segementation Fault>

5. Débordement de pile

Ce n'est pas un problème lié au pointeur, même le code peut ne pas avoir un seul pointeur. C'est à cause d'un manque de mémoire sur la pile. Il s'agit également d'un type de corruption de mémoire pouvant survenir en raison d'une grande taille de tableau, d'un grand nombre d'appels récursifs, de nombreuses variables locales, etc.

Exemple:

C




// C program to illustrate the> // segmentation fault due to> // stack overflow> #include> int> main()> {> >int> arr[2000000000];> >return> 0;> }>

>

>

C++




// C++ program to illustrate> // the segmentation fault> // due to stack overflow> #include> using> namespace> std;> int> main()> {> >int> array[2000000000];> >return> 0;> }>

>

>

Sortir

Segmentation Fault>

6. Débordement de tampon

Si les données stockées dans le tampon sont supérieures à la taille allouée du tampon, un débordement de tampon se produit, ce qui conduit à une erreur de segmentation. La plupart des méthodes du langage C n'effectuent pas de vérification des limites, donc un débordement de tampon se produit fréquemment lorsque nous oublions d'attribuer la taille requise au tampon.

Exemple:

C




// C program to illustrate the> // segementation fault due to> // buffer overflow> #include> int> main()> {> >char> ref[20] =>'This is a long string'>;> >char> buf[10];> >sscanf>(ref,>'%s'>, buf);> >return> 0;> }>

>

>

C++




// C++ program to illustrate the> // segementation fault due to> // buffer overflow> #include> using> namespace> std;> int> main()> {> >char> ref[20] =>'This is a long string'>;> >char> buf[10];> >sscanf>(ref,>'%s'>, buf);> >return> 0;> }>

>

>

Sortir

Segmentation Fault>

7. Déréférencer un pointeur non initialisé ou NULL

C'est une erreur de programmation courante que de déréférencer un pointeur non initialisé ( pointeur sauvage ), ce qui peut entraîner un comportement indéfini. Lorsqu'un pointeur est utilisé dans un contexte qui le traite comme un pointeur valide et accède à sa valeur sous-jacente, même s'il n'a pas été initialisé pour pointer vers un emplacement mémoire valide, cette erreur se produit. Cela peut entraîner une corruption des données, des erreurs de programme ou des erreurs de segmentation. En fonction de leur environnement et de leur état lors du déréférencement, les pointeurs non initialisés peuvent donner des résultats différents.

Comme nous le savons, le pointeur NULL ne pointe vers aucun emplacement mémoire, donc son déréférencement entraînera une erreur de segmentation.

Exemple:

C




// C program to demonstrate segmentation> // fault when uninitialized pointer> // is accessed> #include> int> main()> {> >int>* ptr;> >int>* nptr = NULL;> >printf>(>'%d %d'>, *ptr, *nptr);> >return> 0;> }>

>

>

C++




// C++ program to demonstrate segmentation> // fault when uninitialized pointer> // is accessed> #include> using> namespace> std;> int> main()> {> >int>* ptr;> >int>* nptr = NULL;> >cout << *ptr <<>' '> << *nptr;> >return> 0;> }>

>

>

Sortir

Segmentation Fault>

Comment réparer les défauts de segmentation ?

On peut corriger les erreurs de segmentation en faisant attention aux causes évoquées :

  • Évitez de modifier les littéraux de chaîne.
  • Soyez prudent lorsque vous utilisez des pointeurs car ils constituent l’une des causes les plus courantes.
  • Tenir compte de la taille du tampon et de la pile avant de stocker les données pour éviter un débordement de tampon ou de pile.
  • Vérification des limites avant d'accéder aux éléments du tableau.
  • Utilisez scanf() et printf() avec précaution pour éviter des spécificateurs de format incorrects ou un débordement de tampon.

Dans l’ensemble, la cause de l’erreur de segmentation est l’accès à la mémoire qui ne vous appartient pas dans cet espace. Tant que nous évitons de faire cela, nous pouvons éviter la faute de segmentation. Si vous ne parvenez pas à trouver la source de l'erreur même après l'avoir fait, il est recommandé d'utiliser un débogueur car cela mène directement au point d'erreur dans le programme.