Partage
  • Partager sur Facebook
  • Partager sur Twitter

Ereur de segmentation

(core dumped)

    17 janvier 2018 à 20:15:50

    Bonjour tout le monde

    Voilà j'ai ce code et ai une ereur de segmentation et je ne sais pas d'où est ce

    qu'elle sort si quelqu'un pouvait m'aider ce serai cool merci ! 

    Mon but ici est de remplir chaque nœud de l'arbre avec une chaîne de caractère prise dans un fichier dans mon cas. Tâche peu facile 

    #include <stdlib.h> 
    #include <stdio.h>
    #include<string.h>
    #define TAILLE_MAX 100
    
    
    
    typedef struct noeud //structure de l'arbre
    	{
    	    int info;	
    	    char tableau[TAILLE_MAX];
    	    struct noeud *sag, *sad;
    	}noeud;
    
    typedef noeud *node;
    
    node Singleton(int e) // Création du singleton
    {
    	node t = malloc(sizeof(noeud));
    	t->info = e;
    	t->sag = t->sad = NULL;
    	return t;
    }
    
    void ParcoursPreordre(node t)
    {
    
        FILE* fichier = NULL;
        char chaine[3] ;
        fichier = fopen("text.txt", "r");
    
     
    
        if (fichier != NULL)
    
        {
    	fgets(chaine, TAILLE_MAX, fichier);
            printf("Les meilleurs scores sont : %s", chaine);
        }
     
    strcpy(t->tableau,chaine);
    ParcoursPreordre(t->sag);
    ParcoursPreordre(t->sad);
    
    } 
     
    
    
    
    node new_perfect_tree(int n, int e) // Création de l'arbre parfait
    {
    	if (n <= 0) return NULL;
    	node t = Singleton(e);
    	t->sag = new_perfect_tree(n - 1, 2*e);
    	t->sad = new_perfect_tree(n - 1,  2*e+1);
    	return t;
    }
    
    
    void print_prefix(char c, int n) { while (n--) putchar(c); } // Affiche la numérotation de l'arbre
    
    void print_tree(node t, int p) {
    	print_prefix('-', 2 * p);
    	if (!t) printf("x\n");
    	else {
    		printf("%d\n", t->info);
    		if(t->sag || t->sad){      		// affiche les sous arbres        
    			print_tree(t->sag, p + 1);	//gauche
    			print_tree(t->sad, p + 1);	//droit
    		}
    	}
    }
    
    int main(int argc, char** argv)
    {	
    	node t = new_perfect_tree(3, 1);
        ParcoursPreordre(t);	
    	print_tree(t,0);
    
    	return 0;
    }
    



    • Partager sur Facebook
    • Partager sur Twitter
      17 janvier 2018 à 20:34:59

      La lecture du fichier n'est pas correcte, tu l'ouvres récursivement, donc tu ne lis que la première ligne et tu ne le fermes jamais !
      • Partager sur Facebook
      • Partager sur Twitter
        17 janvier 2018 à 21:01:11

        En gros quand on ouvre récursivement une fonction d'ouverture de fichier il y a erreur de segmentation ?

        Pourtant même quand je fais ça j'ai erreur 

        void ParcoursPreordre(node t)
        {
        
            FILE* fichier = NULL;
            char chaine[3] ;
            fichier = fopen("text.txt", "r");
        
         
        
            if (fichier != NULL)
        
            {
        	fgets(chaine, TAILLE_MAX, fichier);
                printf("Les meilleurs scores sont : %s", chaine);
            }
         
        /*strcpy(t->tableau,chaine);
        ParcoursPreordre(t->sag);
        ParcoursPreordre(t->sad);
        */
        } 



        -
        Edité par Game of throtinette 17 janvier 2018 à 21:04:12

        • Partager sur Facebook
        • Partager sur Twitter
          18 janvier 2018 à 8:20:51

          Bonjour,

          Je passais par là ... je ne comprends pas pourquoi le "fgets" utilise une "chaine[3]" avec TAILLE_MAX qui vaut "100" ;

          Ensuite, c'est sûr que quand les ParcoursPreordre seront décommentés, on réouvrira le fichier à chaque tour, en lisant toujours la 1ere ligne ...

          -
          Edité par MichelBuono 18 janvier 2018 à 8:22:52

          • Partager sur Facebook
          • Partager sur Twitter
            18 janvier 2018 à 9:18:15

            Oui c'est une ereur j'ai remplacé le chaine[3] par TAILLE_MAX.

            Est ce que vous savez comment je peux remplir les noeud d'un arbre avec chacun une chaine de caractère différente ? 

            • Partager sur Facebook
            • Partager sur Twitter
            Anonyme
              18 janvier 2018 à 9:20:59

              Le problème SIGSEV survient ligne 42, car ta fonction récursive n'as pas de condition d'arrêt, donc tu fais tout le temps ParcoursPreordre(t->sag);, sauf qu'au bout d'un moment, t vaut NULL.

              Maintenant, le vrai probleme, c'est clairement la logique de ton code. Ta fonction new_perfect_tree créé un arbre d'une certaine taille, sauf que ta fonction ParcoursPreordre n'en tient pas compte.

              + les remarques de MichelBuono : Un fgets de 100 avec un buffer de 3 ... tu aimes te faire du mal ...
              • Partager sur Facebook
              • Partager sur Twitter
                18 janvier 2018 à 9:47:09

                C'est difficile de vous répondre rapidement, dans la mesure où je ne sais pas si une partie du code vous a été donnée et doit être respectée ou si vous avez tout créé de zéro ...
                En plus, les arguments des fonctions ne sont pas documentés, ce qui n'aide pas à la compréhension globale du programme.

                En général, un arbre se construit et se remplit progressivement :

                le premier noeud n'a pas de père ( sag est NULL)
                le dernier noeud n'a pas de fils (sad est NULL)
                les noeuds intermédiaires ont à la fois un père et un fils non NULL

                La plupart du temps, on crée une fonction qui retourne l'adresse du 1er noeud à partir de l'adresse d'un noeud quelconque
                et
                une fonction qui renvoie l'adresse du dernier noeud à partir de l'adresse d'un noeud quelconque
                ce qui permet :
                de se positionner en début d'arbre pour, par exemple, imprimer l'arbre ou y effectuer une recherche
                de se positionner en fin d'arbre pour ajouter un nouveau noeud.

                On fait aussi une fonction d'ajout de noeud à partir des données du nouveau noeud (votre chaîne de caractères lue dans le fichier) et de l'adresse du dernier noeud de l'arbre (NULL quand l'arbre n'existe pas encore) ; Le noeud que l'on crée pointera alors vers son père (sag) ou NULL et son fils (sad) sera NULL puisque c'est le dernier noeud de l'arbre.

                Si l'on veut, on peut aussi créer une fonction d'insertion de nouveau noeud avant ou après un noeud donné ...

                Dans ce contexte, pour remplir l'arbre, je lirais le fichier ligne à ligne en créant un noeud à chaque lecture, ce noeud étant rattaché au précédent (sauf le 1er qui sera sans père)

                Bon, si je n'ai pas compris votre problème, oubliez tout ça !

                Bon courage

                • Partager sur Facebook
                • Partager sur Twitter
                  18 janvier 2018 à 13:32:08

                  Mais attend je suis pas du tout d'accord avec ce que tu me dis là. Tout d'abord on crée un noeud qui n'a pas de père qui sera à la tête de l'arbre, d'accord. 

                  Mais sag et sad sont ses fils. SAG le fils gauche et SAD le fils droit. 

                  Je n'ai pas de fonction qui sont obligatoire je dois juste réaliser un arbre fonctionnel et ça de n'importe quelle manière tant que je le comprend. 

                  SAG = sous arbre gauche

                  SAD = sous arbre droit 

                  SofEvans2 a écrit:

                  Le problème SIGSEV survient ligne 42, car ta fonction récursive n'as pas de condition d'arrêt, donc tu fais tout le temps ParcoursPreordre(t->sag);, sauf qu'au bout d'un moment, t vaut NULL.

                  Maintenant, le vrai probleme, c'est clairement la logique de ton code. Ta fonction new_perfect_tree créé un arbre d'une certaine taille, sauf que ta fonction ParcoursPreordre n'en tient pas compte.

                  + les remarques de MichelBuono : Un fgets de 100 avec un buffer de 3 ... tu aimes te faire du mal ...

                  Merci c'est vrai que j'ai oublié de mettre des condition. Mais es tu sure que le "fopen" qui apparaît récursivement ne pose pas de problème ? Par là je veux dire que l'ouverture multiple du même fichier ne va pas créer l’erreur de segmentation. 

                  -
                  Edité par Game of throtinette 18 janvier 2018 à 13:35:17

                  • Partager sur Facebook
                  • Partager sur Twitter
                    18 janvier 2018 à 13:49:29

                    Game of throtinette a écrit:

                    Mais attend je suis pas du tout d'accord avec ce que tu me dis là.

                    Désolé, je suis parti sur une autre organisation de données, du genre liste chaînée ...
                    • Partager sur Facebook
                    • Partager sur Twitter
                      18 janvier 2018 à 13:55:58

                      Ah d'accord pas de soucis

                      -
                      Edité par Game of throtinette 18 janvier 2018 à 13:56:58

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Anonyme
                        18 janvier 2018 à 14:12:06

                        Game of throtinette a écrit:

                        Merci c'est vrai que j'ai oublié de mettre des condition. Mais es tu sure que le "fopen" qui apparaît récursivement ne pose pas de problème ? Par là je veux dire que l'ouverture multiple du même fichier ne va pas créer l’erreur de segmentation. 

                        -
                        Edité par Game of throtinette 22 minutes ago


                        Comme je l'ai dit, c'est un peu la logique du code qui me semble pas stable.
                        Pourquoi créer un arbre de n profondeur sans avoir de données ?

                        Si c'est un code que tu fais pour toi, je te conseil de faire un arbre AVL (ou rouge / noir).
                        Si c'est un code pour l'école et que tu n'as pas le choix, ben tant pis, on fera avec.

                        Maintenant, ta fonction ParcoursPreOrder est clairement erronée.
                        Le "mieux", c'est de faire une fonction ParcoursPreOrder qui prends en argument ton arbre + le chemin vers le fichier qui sera utilisé.
                        Dans cette fonction, tu ouvres le fichier (n'oublie pas la gestion erreur) et tu appel une 2eme fonction.

                        Cette 2eme fonction prends en arguments  ton arbre + un FILE*
                        Si arbre != NULL  -->>   tu récupère ce qu'il faut dans le fichier (gestion erreur), tu affecte à ton nœud, et tu appelles de nouveau la 2eme fonction (récursif).

                        Le problème avec ce type d'architecture, c'est que tu ne saura pas si le fichier contenait assez de données par rapport à ton arbre (ou trop).
                        C'est pour cela que je dit que c'est bancale ...

                        De plus, l’intérêt primaire d'un arbre binaire est de pouvoir trouver rapidement un nœud.
                        Il doit donc y avoir une logique (par exemple, si les noeud de ton arbre contienne des nombres, alors le fils gauche contient des nombres inférieur au nombre du nœud, et le fils droit contient les nombres supérieur). Or, en affectant aveuglement des valeurs contenu depuis le fichier, on n'a aucune garantie que la "logique" de l'arbre soit respecté. Et comme tu n'as alloué qu'une profondeur de "n", si en réorganisant ton arbre tu tombes sur des valeurs de profondeur "n + 1", tu vas devoir faire des permutations qui ressembleront fort aux permutations d'un arbre AVL (et ce n'est pas si trivial que cela).

                        Bref, si c'est un devoir d'école, ben, tant pis, sinon, change ton fusil d'épaule.
                        • Partager sur Facebook
                        • Partager sur Twitter
                          18 janvier 2018 à 15:26:01

                          Hello,

                          Il y a un nombre maximum de fichiers de type FILE * qui peuvent être ouverts simultanément. Si mes souvenirs sont exacts, chez moi, ce nombre est de 50 fichiers.

                          Je n'ai jamais été jusque là, mais je suppose qu'arrivé là, le fopen() renvoie NULL

                          • Partager sur Facebook
                          • Partager sur Twitter

                          On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

                          Anonyme
                            18 janvier 2018 à 15:49:30

                            Uuuh, sous Debian, ce nombre est de 65536 par processus et de 391132 au total (oui je sais, ca dépend de l'OS est de sa configuration, mais la c'est la conf par défaut).
                            50 me parait misérablement petit, surtout pour des serveurs de BDD style Oracle, PostgreSQL, etc etc.

                            En tout les cas, errno contient EMFILE ou ENFILE, donc c'est assez facile à voir.
                            • Partager sur Facebook
                            • Partager sur Twitter

                            Ereur de segmentation

                            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                            • Editeur
                            • Markdown