Flux rss
Collection CommentÇaMarche.net

[Langage C] C/C++ Erreur de segmentation

Bookmark Ajouter aux favoris / Partager
Dernière mise à jour le 8 septembre 2007 à 14:21 par kilian
Publié par kilian

Qu'est ce qu'une erreur de segmentation



Vous êtes en train de développer une application sous Linux en
C/C++. Tout va bien, ça compile, les oiseaux chantent.
Donc vous lancez votre application pour la tester.

Et vous obtenez l'un de ces deux messages:
Erreur de segmentation

ou
Segmentation fault

Autant lorsque vous avez une erreur avec un programme écrit dans un langage de très haut niveau (perl, python, java etc...), vous aurez un message de debuggage détaillé: quel type d'exception s'est produit? A quel ligne du programme ça correspond etc...
Autant avec un langage compilé (donc transformé en langage directement compréhensible par votre processeur) comme c ou c++, votre programme n'est sous la tutelle d'aucun interpréteur ou machine virtuelle. Donc personne pour surveiller vos erreurs et les analyser.

Heureusement il existe des programmes appelés debuggeurs et qui sont là pour vous faciliter la tâche.

Il faut savoir qu'un système d'exploitation moderne (Windows nt/2000/XP/ ; Linux) alloue une portion de mémoire pour chaque application. Si une application essaie de pénétrer directement dans une zone-mémoire qui ne lui appartient pas ou dans une zone mémoire incorrecte, le système d'exploitation va stopper l'application en cours et va générer une erreur (sous Linux: Erreur de segmentation)

En C


Prenons par exemple un programme en C tout à fait débile qui se plante volontairement et génère une erreur de segmentation:

void lance_erreur_segmentation()
{
	int *pointeur_dangereux=(int *) 100;
	int test=*pointeur_dangereux;
}

int main(int argc, char ** argv)
{
	lance_erreur_segmentation();
	return 0;
}


Dans la fonction lance_erreur_segmentation, le pointeur_dangereux pointe vers l'adresse 100 dans la mémoire.
C'est une adresse qui ne peut pas appartenir à une application normale.
Au moment où pointeur_dangereux tentera de lire ce qu'il ya dans l'adresse mémoire 100 pour mettre la valeur située à cette adresse dans la variable test, le programme va crasher.
Et vous obtiendrez le message "Erreur de segmentation".

Pour débugger ce programme nous allons commencer par le compiler en lui chargeant ses symboles de débuggage. Cela permet notamment de charger les noms de fonctions et variables utilisés dans le programme une fois qu'il est compilé, ainsi le debugger pourra tracer l'erreur en vous indiquant les noms des fonctions concernées plutôt que de donner juste leur adresse.
Je parle ici de l'option -g

On compile:
gcc -g test.c -o test

Et on lance le programme dans le debugger:
gdb ./test

Vous allez apercevoir une invite de commande commençant par:
(gdb)

Tapez la commande run

Observons ce qu'il se passe:
(gdb) run
Starting program: /home/chantecode/Desktop/test 

Program received signal SIGSEGV, Segmentation fault.
0x08048334 in lance_erreur_segmentation () at test.c:4
4               int test=*pointeur_dangereux;


Que demander de plus: le debuggeur vous indique la ligne dans votre fichier source qui est à l'origine de l'erreur, ainsi que la fonction concernée et le contenu de la ligne:
C'est une erreur dans la fonction lance_erreur_segmentation dans le fichier source test.c à la ligne 4 dont le contenu est
int test=*pointeur_dangereux;


Admettons maintenant que vous vouliez savoir quelle fonction a appelé quelle autre fonction depuis le début du programme jusqu'à l'arrivée de l'erreur.

Tapez la commande bt:
(gdb) bt
#0  0x08048334 in lance_erreur_segmentation () at test.c:4
#1  0x0804834e in main () at test.c:9

Et vous avez encore une fois ce qu'il vous faut :-)

En C++


Pour en rester au même problème: les erreurs de segmentation, il n'y a pas grand chose à ajouter pour le C++, hormis qu'il s'agit d'utiliser la commande g++ avec l'option -g de la même façon qu'avec gcc.

Le rapport de gdb sera le même mais avec des détails sur les classes concernées.

Exemple:
//Fichier test.cpp
class Test{
	public:
		int a;
		Test(){};
		~Test(){};
		int incremente_a(){ a++; };
};

int main()
{
	Test *t;
	t=(Test *)100;
	t->incremente_a();
	return 0;
}

On compile comme ceci:
g++ -g test.cpp -o test


On lance le déboggeur:
gdb ./test

Puis on y tape les mêmes commandes qu'avant et tous les détails s'affichent:
(gdb) run
Starting program: /home/chantecode/Desktop/test 

Program received signal SIGSEGV, Segmentation fault.
0x080483fc in Test::incremente_a (this=0x64) at test.cpp:7
7                       int incremente_a(){ a++; };
(gdb) bt
#0  0x080483fc in Test::incremente_a (this=0x64) at test.cpp:7
#1  0x080483e7 in main () at test.cpp:14


Et voilà.

Liens


_ Excellent tutoriel sur le déboggage C++ en utilisant gdb de manière plus agréable(fr)
[visual C++] erreur icone Bonjour!!!! Je suis en train de créer une application sur visual c++ express 2005 et j'ai voulu mettre une icone pour la fenetre principale à côté du titre de la form mais j'ai une erreur lorsque je lance l'application : Une exception non gérée du... www.commentcamarche.net/forum/affich-2716593-visual-c-erreur-icone
[C] Erreur de segmentation Bonjour, Je compile mon programme en faisant un make lorsque j'execute mon programme, j'obtiens une erreur de segmentation Avec gdb, j'obtiens ceci : Program received signal SIGSEGV, Segmentation fault. 0xb7e52c20 in strcpy () from... www.commentcamarche.net/forum/affich-2253753-c-erreur-de-segmentation
[C++] Erreurs de compilation ! (Résolu) Bonjour, Mon programme ne s'exécute pas et je n'arrive pas à détecter mes erreurs : Voilà le code : #include using namespace std; class C { int *v; public: C(int x); ~C(); C(C c); int getv(); }; C::C(int x) { v=new int(x); cout www.commentcamarche.net/forum/affich-4338527-c-erreurs-de-compilation
La compilation et les modules en C et en C++Cet article a pour vocation d'introduire les notions de bases de la compilation en C et en C++ et de la programmation modulaire. Il permet de mieux comprendre les messages d'erreur du compilateur. Les notions abordées ici sont indépendantes du... www.commentcamarche.net/faq/sujet-14440-la-compilation-et-les-modules-en-c-et-en-c
[Windows XP] Erreur 0x100000d1 (Minidump)L'ordinateur a redémarré après une vérification d'erreur. La vérification d'erreur était : 0x100000d1 (0x0000000c, 0x00000002, 0x00000000, 0xaa6a6f21). Un vidage a été enregistré dans : C:\WINDOWS\Minidump\Minixxxxx.dmp Ce problème se pose quand le... www.commentcamarche.net/faq/sujet-4938-windows-xp-erreur-0x100000d1-minidump
[Turbo C] erreur processeur NTVDM lorsque j instal (Résolu)bonjour alors voila j essaye d installer le turbo C (je sais y a mieu mais c'est celui utilisé a l école donc pas trop le choix...) et lors de l instalation j ai l erreur suivante le processeur NTVDM a rencontré une instruction non autorisée.... www.commentcamarche.net/forum/affich-1342377-turbo-c-erreur-processeur-ntvdm-lorsque-j-instal
Microsoft Visual C++ Runtime LibraryBonjour à tous et merci à ceux qui liront ce message. Je suis sous Windows 2000. Lorsque je joue à un jeu (CS, AOM, NWN), le message d'erreur suivant s'affiche au début de la partie : Microsoft Visual C++ Runtime Library Runtime error! program : « le... www.commentcamarche.net/forum/affich-212424-microsoft-visual-c-runtime-library
[Visual C++]Erreur à l'execution avec des dllsalut, j'ai un probleme sous visual(je decouvre ce logiciel!) mon programme compil mais lorsque je veux l'executer la console s'affiche puis disparait quasi directement et j'ai ensuite un tas d'erreur du genre : 'joao.exe' : Chargé... www.commentcamarche.net/forum/affich-2723991-visual-c-erreur-a-l-execution-avec-des-dll