FAQ CConsultez toutes les FAQ
Nombre d'auteurs : 35, nombre de questions : 194, dernière mise à jour : 18 février 2018 Ajouter une question
Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums de www.developpez.com et de l'expérience personnelle des auteurs.
Je tiens à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes ; les auteurs font le maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous trouvez une erreur, ou que vous souhaitez devenir rédacteur, lisez ceci .
Sur ce, je vous souhaite une bonne lecture.
- Qu'est-ce qu'une erreur de segmentation, ou segfault ?
- Comment sont provoquées les erreurs de segmentation ?
- Pourquoi mon programme provoque-t-il une erreur de segmentation ?
- Que faire pour comprendre l'origine de l'erreur de segmentation ?
- Que faire pour détecter les erreurs liées aux accès (lecture ou écriture) mémoire ?
- Qu'est-ce qu'un pointeur invalide (non initialisé) ?
- Qu'est-ce qu'un dépassement de tableau ?
- Qu'est-ce qu'un débordement de pile ?
- Qu'est-ce qu'un pointeur invalide (pointeur référençant un espace mémoire n'étant plus valide) ?
Il s'agit d'une erreur très courante qui se produit lorsque votre programme essaie de lire ou d'écrire dans une zone mémoire qui ne lui a pas été attribuée par le système d'exploitation.
Par défaut, un programme en langage machine a accès sans restriction à la totalité du plan mémoire de la machine. C'est de cette façon que fonctionnaient les anciennes architectures telles que les 8 bits, la plupart des microcontrôleurs et les ordinateurs compatibles PC en mode réel (notamment sous D.O.S.). Néanmoins, si ce programme s'avère défectueux et se met à écrire de manière incontrôlée dans la mémoire vive, il peut écraser ce qui s'y trouve : ses propres données, les données sur le disque ou encore le système d'exploitation.
Puisqu'un programme en langage machine est, par définition, exécuté directement par le microprocesseur, sans couche intermédiaire, il n'est pas possible de mettre en place un contrôle logiciel pour empêcher un tel programme de mal se comporter. Pour remédier à cela, les architectures modernes embarquent un dispositif électronique placé soit directement au sein du microprocesseur, soit dans l'unité de gestion de la mémoire permettant de vérifier si les adresses mémoire présentées sur le bus sont comprises dans des limites fixées à l'avance. Si ce n'est pas le cas, une « exception » est déclenchée. Celle-ci provoque un renvoi immédiat vers un sous-programme du système d'exploitation qui, en l'absence d'instructions spécifiques, met fin au programme fautif.
Notez également que le système d'exploitation alloue une plage de travail au processus qui l'organise ensuite comme bon lui semble. Cela signifie qu'il mettra fin à un programme essayant d'écrire sur les autres processus, mais qu'il le laissera faire s'il écrase ses propres données. Ainsi, un logiciel qui ne plante pas n'est pas forcément correct pour autant. Des données invalides peuvent apparaître après coup, et un programme réputé fonctionnel peut devenir défectueux sans explication lorsqu'il est compilé sur une autre architecture.
En langage C, une erreur de segmentation est provoquée dans la grande majorité des cas par un pointeur invalide. Elle peut également être le fait d'un dépassement de tableau ou d'un débordement de pile.
Lorsque vous êtes confrontés à une erreur de segmentation, lancez votre programme dans un débogueur. Ce dernier s'arrêtera automatiquement à la ligne provoquant le crash. Examinez la ligne incriminée et voyez si elle utilise un pointeur (où l'adresse d'une variable obtenue avec l'opérateur « & », par exemple). Il est très probable que la valeur de celui-ci soit incorrecte, obsolète, ou qu'elle référence un objet trop petit pour recevoir ce qu'on veut lui affecter. Grâce au débogueur, vous pouvez rapidement déterminer l'origine du crash, en affichant la valeur du pointeur ou de l'index du tableau incriminé à la ligne où le débogueur s'est arrêté.
Le débogueur ne vous aidera pas toujours, notamment si le l'erreur de segmentation est provoquée par une corruption de la mémoire ayant eu lieu plus tôt dans l'exécution du programme.
Pour cela, il existe un autre type de programmes, les analyseurs de mémoire, qui eux vont vous permettre de détecter les erreurs liées à la mémoire (même si cela ne provoque pas de plantage) ainsi que des fuites de mémoire.
Sous Linux, vous avez valgrind. Sous Windows, l'équivalent est Dr Memory. Vous pouvez aussi utiliser MTuner.
Le code suivant provoque une erreur de segmentation :
Code C : | Sélectionner tout |
1 2 3 | char * ptr; strcpy (ptr,"Test"); |
Le code suivant provoque une erreur de segmentation :
Code C : | Sélectionner tout |
1 2 3 4 5 6 | int buffer[256], i; for (i=0 ; i<512 ; i++) { buffer[i] = 0; } |
À noter que dans le cas de dépassements légers, de l'ordre d'un ou deux éléments seulement après la fin du tableau, il est probable que l'opération ne provoque pas d'erreur de segmentation, mais écrase les variables situées immédiatement après le tableau. Celles-ci voient alors leur valeur modifiée de façon indéfinie et sans avertissement, provoquant des bogues très difficiles à localiser.
Le code suivant provoque une erreur de segmentation :
Code C : | Sélectionner tout |
1 2 3 4 | void f() { f(); } |
Code C : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <stdio.h> int * calcul (int a, int b) { int resultat; resultat = a + b; return &resultat; } int main (void) { int * r; r = calcul(1,2); printf ("Résultat : %d\n", *r); return 0; } |
Généralement cet exemple produit un avertissement lors de la compilation.
Dans ce cas précis, il est probable que cet espace ne soit pas rendu immédiatement au système. Si la pile a été utilisée entre l'appel à calcul() et celui à printf() (par exemple à la suite d'une interruption), cette dernière renverra à l'écran un résultat indéfini. Dans le cas contraire, la mémoire sera restée dans l'état où on l'a laissée, renverra la bonne valeur, et donnera l'illusion que le programme fonctionne correctement alors qu'il n'en est rien.
Proposer une nouvelle réponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour çaLes sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.