CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

[C] Segmentation fault

LCoileux
LCoileux
Niveau 7
03 mai 2010 à 19:38:22

Bonjour,
Débutant en C, je suis en train de faire un petit exercice pour m'entrainer.
Le but est de remplir une liste de containers dans un nombre de silos ayant une hauteur max, puis de les afficher
J'ai essayé cet algo pour remplir:

void remplir1(LesSilos stockage, int nbSilos, int hMax, GSList *liste){
int nbContainers = g_slist_length(liste);
int containerEnCours = 0;
int siloEnCours = 0;
int hauteurRestante = hMax;
int silos = nbSilos;
while((nbContainers > 0) && (silos > 0)) {
Element *elt = (Element*)g_slist_nth_data(liste, containerEnCours);
if(hauteurRestante >= elt->hauteurElement){
empiler(stockage[siloEnCours], elt);
containerEnCours++;
nbContainers--;
hauteurRestante = hauteurRestante - elt->hauteurElement;
}
else{
siloEnCours++;
hauteurRestante = hMax;
silos--;
}
}
}

et ceux-ci pour l'affichage:

void ecrireUnElement(gpointer data, gpointer user_data){

Element *elt;

elt = (Element*)data;

printf("Element %s de hauteur %d\n", elt->nomElement, elt->hauteurElement);

}

void ecrireDonnees(GSList *liste){
g_slist_foreach(liste, (GFunc)ecrireUnElement, NULL);

}

void afficherSilos(LesSilos stockage, int n){
int i;
for(i=0; i<n; i++){
ecrireDonnees(stockage[i]);
}
}

Seulement lorsque je lance l'algo de remplissage, j'obtiens une erreur de segmentation lors de l'affichage. Je suppose que les silos ne sont pas remplis, mais je n'en suis pas sur...
Est-ce bien celà ?
Merci d'avance

godrik
godrik
Niveau 30
03 mai 2010 à 20:10:19

il est difficile de donner une reponse sans avoir le code complet.
Mon conseil est (comme toujours quand on a une segfault): fait tourner le code dans valgrind.

tbop2
tbop2
Niveau 10
03 mai 2010 à 20:13:06

Ou passer en debugueur.
Selon ton IDE ça fait plus ou moins peur au début mais avec la ligne qui flanche + les dernières valeurs de variables recensées + la pile d'instruction tu fais souvent très mal !

LCoileux
LCoileux
Niveau 7
03 mai 2010 à 21:02:53

Apres passage dans valgrind, j'obtiens ca:
==25715== Memcheck, a memory error detector
==25715== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==25715== Using Valgrind-3.5.0-Debian and LibVEX; rerun with -h for copyright info
==25715== Command: ./main
==25715==
==25715== Conditional jump or move depends on uninitialised value(s)
==25715== at 0x40877B0: g_slist_foreach (gslist.c:465)
==25715== by 0x8048932: ecrireDonnees (fonctions.c:61)
==25715== by 0x8048BAA: afficherSilos (fonctions.c:153)
==25715== by 0x80487D4: main (main.c:39)
==25715==
==25715==
==25715== HEAP SUMMARY:
==25715== in use at exit: 5,251 bytes in 30 blocks
==25715== total heap usage: 31 allocs, 1 frees, 5,603 bytes allocated
==25715==
==25715== LEAK SUMMARY:
==25715== definitely lost: 1,016 bytes in 2 blocks
==25715== indirectly lost: 0 bytes in 0 blocks
==25715== possibly lost: 671 bytes in 24 blocks
==25715== still reachable: 3,564 bytes in 4 blocks
==25715== suppressed: 0 bytes in 0 blocks
==25715== Rerun with --leak-check=full to see details of leaked memory
==25715==
==25715== For counts of detected and suppressed errors, rerun with: -v
==25715== Use --track-origins=yes to see where uninitialised values come from
==25715== ERROR SUMMARY: 4 errors from 1 contexts (suppressed: 15 from 8)

mais je n'ai jamais utilisé ceci...

godrik
godrik
Niveau 30
03 mai 2010 à 21:43:15

les lignes qui t'interessent sont les suivantes:

==25715== Conditional jump or move depends on uninitialised value(s)
==25715== at 0x40877B0: g_slist_foreach (gslist.c:465)
==25715== by 0x8048932: ecrireDonnees (fonctions.c:61)
==25715== by 0x8048BAA: afficherSilos (fonctions.c:153)
==25715== by 0x80487D4: main (main.c:39)

a la ligne 465 de gslist.c, une condition utilise une zone memoire non initialise. Ca veut probablement dire que tu ne l'a pas initialise auparavant.

chris_27
chris_27
Niveau 10
04 mai 2010 à 15:47:26

« Mon conseil est (comme toujours quand on a une segfault): fait tourner le code dans valgrind. » :d) heu… gdb / ddd plutôt pour un segfault. En pratique, c'est plus simple et plus rapide.

godrik
godrik
Niveau 30
04 mai 2010 à 16:51:07

en moyenne, je trouve l'erruer plus rapidement avec valgrind parceque souvent la seg fault vient d'un autre probleme un peu plus tot dans l'execution. Si la premiere erreur est celle qui caus ela segfault, alors je degaine un debugger.

LCoileux
LCoileux
Niveau 7
04 mai 2010 à 21:46:57

Après verifications en tout genre, il semble que mon probleme vienne directement lorsque j'appelle ma fonction creerLesSilos, qui pour une raison qui m'est totalement inconnue, me rempli automatiquement les deux premiers silos d'un element...

En fait, lorsque dans mon main, je fais:

/*Creation des silos*/
LesSilos mesSilos;
mesSilos = creerLesSilos(4);

et après affichage de la longueur de chaque silo, je me rend compte que les deux premiers valent 1, et les deux derniers 0 (alors que cette fonction est seulement sensé m'allouer la memoire).

Faut-il alors que je "vide" chaque silo crée ? Et si oui, comment puis-je faire ?

godrik
godrik
Niveau 30
04 mai 2010 à 22:00:54

sans le code de la fonction creerlessilo et les structures de donnees associe, il me semble difficile de repondre a la question.

My educated guess would be : tu alloues la memoire, mais ne l'initialise pas.

tbop2
tbop2
Niveau 10
04 mai 2010 à 22:03:50

Un très bon conseil dans ta vie de programmeur : On a le droit d'identifier un problème en essayant de le contourner... Mais on ne le résout pas pour autant !

Si ta fonction bugue tu dois voir d'où ça vient, et pas t'amuser à faire du rafistolage en sortie.

Pour t'aider ils nous manquent les éléments essentiels à mes yeux qui sont : qu'est ce que la structure LesSilos, et deuxièmement que se passe-t-il dans la fonction creerLesSilos.

PS : Si je puis me permettre tu as de très mauvais noms de variables, qui plus est l'anglais c'est mieux en programmation.

LCoileux
LCoileux
Niveau 7
04 mai 2010 à 22:35:31

Ma fonction creerLesSilos:

LesSilos creerLesSilos(int n){
/*Reservation du tableau*/
UnSilo *tab = NULL;

/*Allocation du tableau*/
tab = malloc(n*sizeof(UnSilo));

return tab;
}

Elle ne fait qu'allouer l'espace memoire d'un tableau stockant les pointeurs des listes chainées (qui modelisent les silos).

Mes definitions de type:
typedef GSList *UnSilo;
typedef UnSilo *LesSilos;

godrik
godrik
Niveau 30
04 mai 2010 à 22:50:28

Si tu ne forces pas la taille des silos a une valeures, comment ton programme peut savoir quelle valeure tu souhaites ?
(par ailleurs, qu'est ce que c'est un GSList ?)

LCoileux
LCoileux
Niveau 7
04 mai 2010 à 22:54:31

Une GSList, c'est une liste chainee.
Et je passe la taille de mes silos dans mon algorithme qui va me replir ces silos.

godrik
godrik
Niveau 30
04 mai 2010 à 23:02:44

Je ne sais toujours pas bien ce que je dis parceque tu n'as toujours pas donner de code complet. Mais j'ai quand meme l'impression que apres "tab = malloc(n*sizeof(UnSilo));", les pointeurs dans le tableau ne sont pas initialises a NULL ou a une valeure coherente.

LCoileux
LCoileux
Niveau 7
04 mai 2010 à 23:18:32

En gros, je dois créer mes silos avec cette fonction (qui ne fait qu'allouer la mémoire, et ne remplit pas ces silos). Mes silos ne sont en fait qu'un simple tableau qui vont contenir les pointeurs des listes chainées (GSList).

Il seront remplis qu'avec un autre algo (beaucoup trop gros pour le mettre ici), qui initialisera justement la taille de chaque silo.

Et donc oui, lorsque je crée mon tableau de silo, il n'est pas vide...
Par exemple, lorsque je fais:
LesSilos mesSilos = creerLesSilos(4);

toutes les tailles des silos (que j'obtiens par la fonction g_slist_length) devraient être à 0, vu que je n'ai encore rien mis dedans. Or, certaines sont à 1...

Donc voilà pourquoi je souhaiterais vider mon tableau avant de le remplir (bizarre, car il devrait être vide, mais bon)

C'est un peu dur à expliquer c'est vrai...

tbop2
tbop2
Niveau 10
05 mai 2010 à 00:20:47

Noms de structures et de variables exotiques, aucun copier-coller des définitions, c'est à n'y rien comprendre du tout mon gars !

Tiens, copie-colle le code entier sur ce site et donne nous le lien qu'on y comprenne quelque chose :
http://ideone.com/

dnob700
dnob700
Niveau 10
05 mai 2010 à 00:39:57

"toutes les tailles des silos (que j'obtiens par la fonction g_slist_length) devraient être à 0, vu que je n'ai encore rien mis dedans. Or, certaines sont à 1... "

Non, pour ça il faut d'abord que tu initialise chaque silo. Sinon leur contenu est complètement aléatoire après un malloc et tu ne peut appeler aucune fonction qui va lire ce qu'il y a dans la structure (c'est l'idée du message d'erreur de valgrind qui dit que tu lis une donnée qui n'a pas été initialisé).

LCoileux
LCoileux
Niveau 7
05 mai 2010 à 10:17:39

Mes fonctions: http://ideone.com/DqoYf
Mon main: http://ideone.com/IScMU

LCoileux
LCoileux
Niveau 7
05 mai 2010 à 10:30:25

Désolé pour le double post, mais si dans le main, je fais la déclarations des silos avant celle des containers, je n'ai plus cette erreur...

godrik
godrik
Niveau 30
05 mai 2010 à 16:08:37

Ce n'est pas ca qui cause l'erreur probablement mais :
Ligne 67
" while(fscanf(fichier, "%s %d", nom, &hauteur) != EOF){"
Il faut verifier que fscanf retourne 2 egalement.

Ligne 78 et 80:
" /*Ajout en fin de liste*/
liste = g_slist_prepend(liste, (gpointer)elt);"
Ca, ca ajoute en debut de liste, pas en fin de liste. cf
http://library.gnome.org/devel/glib/stable/glib-Singly-Linked-Lists.html#g-slist-prepend

Ta seg fault vient bien de ce que je pensais, les donnees ne sont pas initialise apres "tab = malloc(n*sizeof(UnSilo));" ligne 130.
La prochaine utilisation de tab[i] que tu fais est : "stockage[siloEnCours] = empiler(stockage[siloEnCours], elt); /*On empile le container*/" Ligne 145.
Ensuite, tu les afficheras avec "g_slist_foreach(liste, (GFunc)ecrireUnElement, NULL);" ligne 110.

Ce qui se passe est que malloc n'initialise pas ses donnes. Du coup, tu peux recuperer NULL ou n'importe quoi. Suivant l'ordre dans lequel tu fais les operations ce qui se trouve dans la memoire que tu alloue est different. D'ailleurs si tu changes d'ordinateur, de compilateur ou de systeme d'exploitation tu aurais un comportement different.

La solution a se probleme est d'initialiser les cases de ton tableau a NULL apres sont allocation:
tab = malloc(n*sizeof(UnSilo));
for (int i=0;i<n;i++)tab[i]=NULL;

ou encore utiliser calloc a la place de malloc.

Sous forums
  • Aide à l'achat Mac
  • Création de Jeux
  • Linux
  • Création de sites web
  • Programmation
  • Internet
  • Steam Deck
  • Macintosh
  • Hardware
La vidéo du moment