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 !!
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); }
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; }
C'est évident ,quand on cherche les ennuis on les trouve ...
Un code comme ça on en rencontre pas tous les jours.
Bon ,je vais essayer de donner des bouts de code mais ça va pas etre
facile car la machine que j'utilise tourne sur linux sans port usb alors il va falloir que j'achete des diskettes et puis monter la partition puis formater pour fat32 pour enfin joindre les fichiers ,hum !
Je peux decement pas taper + de 100 lignes de codes !!!
Mon printf() à moi il est tout bête ,c'est un print de debboguage histoire de savoir si l 'execution passait par là ;du styleTant pis je passe
Code : Sélectionner tout - Visualiser dans une fenêtre à part printf("coucou je suis dans la fonction Defiler()");![]()
Et c'est vrai dans l'autre sens aussi : si tu refuses de voir les erreurs là où elles peuvent être, tu ne risques pas de les trouver.
Cet exemple de code est là pour te montrer qu'il est tout-à-fait possible d'écrire un code légal avec une fonction système qui compile parfaitement et qui, pourtant, plante avant d'avoir affiché le premier caractère…
Il y a neuf chances sur dix que la fonction que tu appelles plante parce que tu lui as passé un paramètre pourri quelque part. Ça peut être directement dans les arguments de la fonction, mais ça peut aussi être dans les membres de ta structure. Et le fait que ça ne plante pas ailleurs n'est pas une raison valable : il y a des dizaines de choses qui peuvent rendre ton bug intermittent.
Il n'y a pas de réseau non plus sur ta machine ? Si vraiment il n'y en a pas, il te coûtera sans doute moins cher, en temps et en argent, d'acheter une carte Ethernet bon marché et un câble.Bon ,je vais essayer de donner des bouts de code mais ça va pas etre
facile car la machine que j'utilise tourne sur linux sans port usb alors il va falloir que j'achete des diskettes et puis monter la partition puis formater pour fat32 pour enfin joindre les fichiers ,hum ! Je peux decement pas taper + de 100 lignes de codes !!!
Rien que dans ce que tu as écrit, il y a déjà une erreur : il manque le retour à la ligne. Si c'est vraiment de cette façon que tu l'as rédigée dans ton code, alors ton message va rester un moment dans le tampon avant d'être affiché et il se peut que l'erreur se produise beaucoup plus loin que tu le crois.Mon printf() à moi il est tout bête ,c'est un print de debboguage histoire de savoir si l 'execution passait par là ;du style
Code : Sélectionner tout - Visualiser dans une fenêtre à part printf("coucou je suis dans la fonction Defiler()");
Sinon, si tu veux savoir tout de suite où se produit l'erreur, il y a un outil formidable pour ça : gdb.
Tu veux dire connecter les 2 ordis ensemble ? Je sais pas faire ça ; par contre si tu pouvais m'en dire un peu plus sur gdb (comment on s'en sert) ça serait un bon début.
Merci
+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