IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Segfault sur **int


Sujet :

C

  1. #1
    Membre régulier
    Homme Profil pro
    Lycéen
    Inscrit en
    Juillet 2010
    Messages
    46
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Juillet 2010
    Messages : 46
    Points : 73
    Points
    73
    Par défaut Segfault sur **int
    Bonjour,

    Mon problème est des plus basiques, mais pour une raison que je ne saisie pas, peut-être due à l'heure "tardive", je n'arrive pas à le résoudre.

    J'ai une liste chaînée, que je veux convertir en tableau, ou plus exactement deux tableau ; un étant en **char (crée puis donné en return), et l'autre en *int (passé par adresse).

    La fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    char **lst_to_arr(t_ls_list *root, int **mt, int *len)
    {
    	t_ls_list *crawler;
    	char **ret;
    	int i;
     
    	*len = 0;
    	if (!root)
    		return (0);
    	crawler = root;
    	*len = lst_size(root);
    	if (!(ret = malloc(sizeof(char*) * *len)) || !(*mt = malloc(sizeof(int) * *len)))
    		return (0);
    	printf("len of %d\n", *len);
    	i = 0;
    	while (i < *len)
    	{
    		ret[i] = strdup(crawler->name);
    		printf("%d at %d\n", crawler->mtime, i);
    		*mt[i] = 12; //crawler->mtime
    		printf("check\n");
    		crawler = crawler->next;
    		++i;
    	}
    	return (ret);
    }
    Son appel:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	tls->targetsc = lst_to_arr(tls->targets, &tls->targetsmt, &tls->targetslen);
    	tls->dirsc = lst_to_arr(tls->dirs, &tls->dirsmt, &tls->dirslen);
    (tls->targetsmt & tls->dirsmt n'étant pas malloc)

    Ma struct:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    typedef struct s_ls_list
    {
    	char *name;
    	int mtime;
    	struct s_ls_list *next;
    } t_ls_list;
    J'ai essayé d'ouvrir gdb pour mieux comprendre ce qu'il se passait, mais j'ai plus été perturbé qu'autre chose:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    (gdb) print *mt[0]
    $1 = 0
    (gdb) print *mt[1]
    Cannot access memory at address 0x0
    (gdb) print *mt[2]
    Cannot access memory at address 0x16
    (gdb) print *(*mt+0)
    $2 = 0
    (gdb) print *(*mt+1)
    $3 = 0
    (gdb) print *(*mt+2)
    $4 = 0
    Mon programme segfault effectivement au deuxième appel (*mt[1] => cannot acces memory ...), cependant, j'ai essayé *mt[1] et *(*mt+1), et ce dernier fonctionne! les deux expression ne sont-elles pas censées revenir au même?

    Je suppose donc que j'ai dû rater mon malloc, n'ayant pas trop l'habitude avec les *int, et encore moins non malloc'd et passées par adresse, mais tout de même, je n'arrive pas à localiser mon erreur.

    Merci d'avance pour votre temps & vos réponses éventuelles.
    Bonne soirée.

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Si tu as un problème avec int**, retire-le de l'équation: place ton int* dans une structure.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Déjà je te rassure: tes malloc() sont bien écris. Attention toutefois, tous tes ret[x] étant des strdup() (des pointeurs alloués) il te faudra bien penser à les libérer un à uns.

    Ceci dit, voici ce que je trouve de dangereux
    • tu fais et testes deux malloc() en parallèle mais tu sors si l'un des deux échoue. Mais que fais-tu de l'autre qui aura (peut-être) réussi ? fuite mémoire assurée. Ceci n'est pas le sujet de ton problème mais autant en parler aussi
    • tu boucles tant que i < *len (je présume que lst_size() te renvoie la bonne taille) mais puisque tu as une liste chainée, pourquoi ne pas l'utiliser et boucler jusqu'à next NULL ? Mais là non plus (sauf si *len n'est pas bon) ça n'est pas problématique
    • tu peux remplacer ton iniitialisation, while() et incrément par un for(), ça ne mange pas de pain et ça allège ton code


    Autre conseil avant d'attaquer le vif: commence par créer un vrai type pour ta liste. Là, tu manipules ta liste en tenant juste son premier élément qui est déjà un pointeur. Ca t'oblige, quand tu veux modifier ce pointeur dans une fonction, de lui passer son adresse laquelle le stocke dans un t_ls_lst ** (j'ai tort ?)
    Par exemple
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    typedef struct s_ls_elem {
    	char *name;
    	int mtime;
    	struct s_ls_elem *next;
    } t_ls_elem;
     
    typedef struct {
    	t_ls_elem *root;
    } t_ls_list;

    Ca peut paraitre con de créer une structure pour un seul élément mais ça a des avantages cachés
    • déjà quand tu as un t_ls_lst liste dans ton main() t'as déjà la mémoire pour ta liste => pas besoin de malloc
    • quand tu passes &liste à une fonction qui la stocke dans un t_ls_lst *pt, celle-ci à instantanément accès à pt->root et peut le modifier si elle a envie (si elle rajoute un élément au début)
    • si tu rajoutes ensuite d'autres éléments de gestion, comme par exemple la taille de ta liste, tes fonctions y ont instantanément accès et t'as plus à t'embêter avec ton lst_size()


    Tu verras, tu allègeras beaucoup de code. Accessoirement si tu lies ton tableau d'entiers avec sa longueur (le *len qui traine un peu partour), autant le lier dans une structure => là aussi ça allègera tes appels (dit aussi par Medinoc pendant que je tapais ce long message )

    Sinon à mon avis ton soucis vient d'ici: *mt[i] = 12; //crawler->mtime. D'ailleurs tu le dis toi-même
    Citation Envoyé par Orci76 Voir le message
    cependant, j'ai essayé *(*mt+1), et ce dernier fonctionne! les deux expression ne sont-elles pas censées revenir au même?
    Pas tout à fait. *(*mt+1) est équivalent à (*mt)[1] (le second élément du tableau d'int pointé par mt) et non *mt[1] (élément pointé par le second pointeur de ton tableau d'int étoiles). T'as oublié les priorités des opérateurs (ceci dit, je ne les connais pas toutes non plus mais je connais surtout celle du pointeur )

    Donc voilà. Mais tu devrais mieux penser tes structures de base, tu aurais un code moins lourd à porter ensuite (ceci dit elles sont quand-même très très bien pensées, je ne vois pas beaucoup de programmeurs ici qui pensent à nommer leurt types "t_xxx" et qui appellent bêtement leur type typedef struct noeud {...} liste et qui se trouvent tout coincés quand ils doivent donner ensuite un nom à leur variable )
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Membre régulier
    Homme Profil pro
    Lycéen
    Inscrit en
    Juillet 2010
    Messages
    46
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Juillet 2010
    Messages : 46
    Points : 73
    Points
    73
    Par défaut
    Salut,

    Merci beaucoup pour ta réponse très détaillée ; après l'avoir vu, j'ai commencé à le rendre plus clair & structuré: c'est effectivement plus pratique.
    Pour les malloc, c'est vrai que j'ai un peu tendance à considérer qu'ils échouent jamais, et je le fais plus pour la forme ; j'ai du coup changé et rajouter un joli free avant mon return ;p.

    J'ai remplacé la ligne dont tu parlais par (*mt)[i], et effectivement, ça fonctionne ; encore une fois, merci beaucoup!
    Il faudrait vraiment que je révise mes prioritées on niveaux des pointeurs ; c'est looiinn d'être la première fois que j'ai ce genre de déconvenues, et je me fais toujours piégé...

    Merci à vous deux, bonne soirée ;).

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Segfault sur un int?
    Par lguignar dans le forum Débuter
    Réponses: 9
    Dernier message: 18/07/2008, 10h03
  2. Segfault sur un int?
    Par lguignar dans le forum C++
    Réponses: 9
    Dernier message: 18/07/2008, 10h03
  3. Segfault sur contructeur de string
    Par lemmel dans le forum SL & STL
    Réponses: 7
    Dernier message: 02/09/2007, 13h50
  4. Test sur int négatif: c'est comment?
    Par Jean_Benoit dans le forum C++
    Réponses: 3
    Dernier message: 08/10/2006, 13h35
  5. erreur ASM inline sur 'INT' avec delphi7
    Par the_magik_mushroom dans le forum Langage
    Réponses: 1
    Dernier message: 03/11/2005, 01h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo