Bonjour à tous ,
je voudrais savoir comment et pourquoi un appel de procédure
est capable de générer l'interruption : segmentation fault
nb: je compile du C avec gcc sous linux.
Bonjour à tous ,
je voudrais savoir comment et pourquoi un appel de procédure
est capable de générer l'interruption : segmentation fault
nb: je compile du C avec gcc sous linux.
Quelques explication ici:
[ame]http://fr.wikipedia.org/wiki/Erreur_de_segmentation[/ame]
Merci pour l'article mais tout cela je le sait déjà ...
Je répète donc la question : comment est-il possible d'obtenir un
segmentation fault provoqué par un appel de procédure ,car c'est
bien cet appel (et pas autre chose) qui provoque la faute !!
Un appel de procédure en C ? Hmm.
Comme le dit Jabbounet, il est peu probable que ce soit l'appel d'une fonction en lui-même qui fasse planter l'affaire, mais plutôt des paramètres initialement invalides exploités par la fonction. Sinon, le seul moyen de faire un appel engendrant une segfault est d'utiliser un pointeur de fonction invalide. Est-ce le cas ?
Sinon, montre-nous ton code.
Bien evidement que cela est bizare sinon je ne poserais pas la question ;
en ce qui concerne le code je ne peux tout mettre mais on va essayer de
procéder par étapes .
la procédure appelante est main et la fonction appelée est la procédure
struct machin *Defiler(void) d'une file implémentée à l'aide d'une liste chainée en laquelle j'ai toute confiance pour 2 raisons : 1)elle fonctionne en dehors de ce programme et
(ce qui est pire) 2)main appelle sans aucun problèmes cette procédure plusieurs fois sans soucis !!
Donc ,il se trouve que lors d'un ultime appel ,le plantage s'effectue sans que
l'execution soit passée à la fonction ?!
J'en suis sûr puisque la première instruction de cette fonction est un printf().
Voilà l'affaire
J'insinue par là que l'on n'utilise pas cette terminologie en langage C.
Merci d'utiliser les balises [ CODE ] (le bouton « # » dans la fenêtre d'édition) pour poster un extrait de code. Pose quand même ton code ici. Au moins le contenu de main(), et le début de Defiler().la procédure appelante est main et la fonction appelée est la procédure
struct machin *Defiler(void)
Et bien, quand tu as passé en revue toutes les causes probables de plantage, il faut commencer à te pencher sur ce que tu avais écarté d'emblée.… d'une file implémentée à l'aide d'une liste chainée en laquelle j'ai toute confiance pour 2 raisons : 1) elle fonctionne en dehors de ce programme et
(ce qui est pire) 2)main appelle sans aucun problèmes cette procédure plusieurs fois sans soucis !!
Et − justement − si tu avais lu les commentaires précédents, tu aurais compris que ce n'est pas un alibi suffisant. Le programme ci-dessous commence également par un printf(). À ton avis, que va-t-il se passer si tu l'exécutes ? Compile cet exemple et lance-le si tu ne le sais pas :Donc ,il se trouve que lors d'un ultime appel ,le plantage s'effectue sans que l'execution soit passée à la fonction ?! J'en suis sûr puisque la première instruction de cette fonction est un printf(). Voilà l'affaire
Code C : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 #include <stdio.h> int main (void) { printf ("%s\n",(const char *)1); return 0; }
Sans nous montrer la partie de ton code qui plante on ne peux pas être plus précis.
As-tu vérifié que les paramètres que tu donne en entrée de ta procédure sont corrects?
Que les variables passées en paramètres sont allouées et ne pointent pas sur des données invalides?
Que ta procédure ne nécessite pas certains pré-requis qui ne sont pas remplis?
....
Même avec des fonctions standard on peux provoquer un segfault si les paramètres d'appel sont incorrect.
Exemple simple qui donne un segfault:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 #include <stdio.h> int main() { int variable_entiere; scanf("%d", &variable_entiere); //correct printf("valeur=%d\n",variable_entiere); scanf("%d", variable_entiere); // segfault printf("valeur=%d\n",variable_entiere); }
+1 gdb un outil indispensable.
En résumé (vite fait, mal fait):
pour savoir exactement ou cela plante, il faut compiler ton application avec les options de debug "-g" pour gcc/g++
Ensuite deux méthodes ensuite sont possible
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 gcc -g monprog.c -o monprog
1/ debug normal
bt est à lancer une fois planté
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 gdb monprog run bt
2/ methode post mortem
Autoriser la génération de fichier core dump.
dans le shell ou lance le programme.
Lancer ton programme pour qu'il génère un fichier core
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 ulimit -c unlimited
faire un debug post mortem avec le fichier core generé pour savoir exactement ou ça plante
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 monprogr ... segfault(core dumped)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 gdb monprog core bt
les deux méthodes sont a peu près équivalente un fois l'application planté.
Cependant la première à l'avantage qu'elle te permet de placer des points d'arrêt, de faire des exécutions pas à pas de ton programme, ..... mais pour cela il faut regarder un peu les tutoriel pour voir comment ça marche.
et en ce qui concerne le suivi de traces, fprintf ( stderr, est bien plus pratique que printf, car il a l'énorme avantage d'être synchrone.. C'est à dire que ce qui n''est pas écrit n'a pas été exécuté, contrairement à printf..
Partager