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

GTK+ avec C & C++ Discussion :

glib: questions formelles et questions de syntaxe


Sujet :

GTK+ avec C & C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 65
    Points : 53
    Points
    53
    Par défaut glib: questions formelles et questions de syntaxe
    Je fais mes premiers pas avec la glib après avoir un peu commencé à étudier GTK+.
    Et j'ai quelques questions formelles et de syntaxe à poser que je vais illustrer au travers d'un exemple de programme simple pêché dans un bouquin.

    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    #include <glib.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    typedef struct
    {
    	int age;
    	char *nom;
    } personne_type;
     
    int compare(personne_type *P1, personne_type *P2)
    {
    	if (P1->age > P2->age)
    		return 1;
    	else 
    		if (P1->age == P2->age)
    		{	if (P1->nom > P2->nom)
    				return 1;
    			else 
    				return -1;
    		}
    		else 
    			return -1;
    }
     
    int main (void)
    {
    	GSList *liste = NULL;
    	personne_type *personne;
     
    	personne = g_malloc(sizeof(personne_type));
    	personne->age = 15;
    	personne->nom = "Jacques";
    	liste = g_slist_insert_sorted(liste, personne,
    				      (GCompareFunc)compare);
     
    	personne = g_malloc(sizeof(personne_type));
    	personne->age = 20;
    /*	personne->nom = "Paul";*/
    	personne->nom = malloc(5);
    	strcpy(personne->nom, "Paul");
    	liste = g_slist_insert_sorted(liste, personne,
    				      (GCompareFunc)compare);
     
    	personne = g_malloc(sizeof(personne_type));
    	personne->age = 15;
    	personne->nom = "Pierre";
    	liste = g_slist_insert_sorted(liste, personne,
    				      (GCompareFunc)compare);
     
    	printf("1 : %s, 2 : %s, 3 : %s\n", 
    	       ((personne_type *)(liste->data))->nom,
    		 ((personne_type *)(liste->next->data))->nom,
    		   ((personne_type *)(liste->next->next->data))->nom);
     
    	g_slist_free(liste);
     
    	return 0;
     
    }
    1/ g_malloc, malloc ou g_try_malloc ?

    a/ Pourquoi utiliser g_malloc plutôt que malloc alors que j'ai lu dans la doc qu'en cas d'échec, elle ne renvoie pas NULL comme malloc mais... plante le programme ?!
    Est-ce qu'il n'ya pas une régression à utiliser g_malloc à ce niveau ?

    b/ Pourquoi alors éventuellement utiliser g_try_malloc qui semble avoir le, même comportement que malloc ?

    2/ g_slist_free ?
    g_slist_free est sensée libérer toute la mémoire de la liste y compris les allocations nécessaires au membre "char *nom" de la structure "type_personne" ?
    Y compris quand j'alloue explicitement avec malloc pour Paul ?

    3/ Comportement interne en cas d'échec de malloc ?
    D'une façon générale, quel est le comportement au sein de la glib en cas d'échec d'allocation mémoire ?
    Le programme plante ? Comportement indéterminé ? Autre ? La doc ne dit rien à ce sujet.
    Je préférerais indiquer l'erreur à l'utilisateur dans l'interface graphique et terminer proprement !

    4/ syntaxe de GList* g_list_find(GList *list, gconstpointer data)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    GList *recherche = NULL;
    guint motif = 15;
     
    recherche = g_list_find (liste, motif);
    a/ Syntaxe ?
    A la compilation, ça plante sur les deux warnings suivants, quel est le problème ?

    warning: passing argument 1 of 'g_list_find' from incompatible pointer type
    warning: passing argument 2 of 'g_list_find' makes pointer from integer without a cast

    b/ Fonctionnement ?
    De toute façon, je ne comprends pas le fonctionnement de g_list_find. D'autant moins que je ne vois pas sur quel membre de la structure il est sensé effectuer la recherche vu qu'on ne le lui dit indique pas. Et d'autre part, il se trouve que la valeur "15" correspond à deux résultats possibles pour l'âge, quel arbitrage fait-il alors ?

    5/ syntaxe de gpointer g_list_nth_data(GList *list, guint n)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	personne = g_list_nth_data (liste, 1);
    Même chose, je ne comprends pas la syntaxe:
    warning: passing argument 1 of 'g_list_nth_data' from incompatible pointer type

    6/ comportement étrange
    Dans mes tests, entre chaque insertion dans la liste, j'avais rajouté un free(personne) juste pour voir.
    Il me sort alors comme résultat surprenant... "1 : Pierre, 2 : Pierre, 3 : Pierre" !!!

    ----------------------

    Pardon pour ce sujet un peu long et toutes ces questions mais je suis dubitatif quant à la glib pour le moment... et du coup j'ai des doutes pour GTK+ également. Mon enthousiasme premier retombe un peu.

  2. #2
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Points : 11 625
    Points
    11 625
    Par défaut
    Citation Envoyé par vitoubien Voir le message
    1/ g_malloc, malloc ou g_try_malloc ?

    a/ Pourquoi utiliser g_malloc plutôt que malloc alors que j'ai lu dans la doc qu'en cas d'échec, elle ne renvoie pas NULL comme malloc mais... plante le programme ?!
    Est-ce qu'il n'ya pas une régression à utiliser g_malloc à ce niveau ?
    Comme dans ton code, beaucoup de personne ne savent ou ne prenne pas la peine de tester le retour de malloc. Et de toutes façons pour quoi faire ?

    Citation Envoyé par vitoubien Voir le message
    2/ g_slist_free ?
    g_slist_free est sensée libérer toute la mémoire de la liste y compris les allocations nécessaires au membre "char *nom" de la structure "type_personne" ?
    Y compris quand j'alloue explicitement avec malloc pour Paul ?
    Non c'est à toi de libérer les données de chaque noeu.

    Citation Envoyé par vitoubien Voir le message
    3/ Comportement interne en cas d'échec de malloc ?
    D'une façon générale, quel est le comportement au sein de la glib en cas d'échec d'allocation mémoire ?
    Le programme plante ? Comportement indéterminé ? Autre ? La doc ne dit rien à ce sujet.
    http://git.gnome.org/cgit/glib/tree/glib/gmem.c#n122

    Citation Envoyé par vitoubien Voir le message
    Je préférerais indiquer l'erreur à l'utilisateur dans l'interface graphique et terminer proprement !
    Tu n'as plus de mémoire disponible, n'espère même pas afficher une boite de dialogue. Et sous Linux le système aura déjà fait le boulot pour toi en tuant le processus qui prend le plus de mémoire.

    Citation Envoyé par vitoubien Voir le message
    4/ syntaxe de GList* g_list_find(GList *list, gconstpointer data)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    GList *recherche = NULL;
    guint motif = 15;
     
    recherche = g_list_find (liste, motif);
    a/ Syntaxe ?
    A la compilation, ça plante sur les deux warnings suivants, quel est le problème ?

    warning: passing argument 1 of 'g_list_find' from incompatible pointer type
    warning: passing argument 2 of 'g_list_find' makes pointer from integer without a cast
    Pour le premier paramètre, tu as confondu liste (GSList) et recherche (GList), pour le second paramètre, il faut passer par un pointeur à l'aide de GINT_TO_POINTER

    Citation Envoyé par vitoubien Voir le message
    b/ Fonctionnement ?
    De toute façon, je ne comprends pas le fonctionnement de g_list_find. D'autant moins que je ne vois pas sur quel membre de la structure il est sensé effectuer la recherche vu qu'on ne le lui dit indique pas.
    Sur le champs data qui contient les données que tu lui fournis. Mais attention, c'est une simple comparaison entre pointer. Il y a de grandes chances que pour les chaines de caractères ça ne fonctionne pas. Il faut alors utiliser g_list_find_custom

    Citation Envoyé par vitoubien Voir le message
    Et d'autre part, il se trouve que la valeur "15" correspond à deux résultats possibles pour l'âge, quel arbitrage fait-il alors ?
    Il te renvoi le premier qu'il va trouver, selon son algorithme de recherche.

    Citation Envoyé par vitoubien Voir le message
    5/ syntaxe de gpointer g_list_nth_data(GList *list, guint n)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	personne = g_list_nth_data (liste, 1);
    Même chose, je ne comprends pas la syntaxe:
    warning: passing argument 1 of 'g_list_nth_data' from incompatible pointer type
    Même remarque que plus haut : GINT_TO_POINTER

    Citation Envoyé par vitoubien Voir le message
    6/ comportement étrange
    Dans mes tests, entre chaque insertion dans la liste, j'avais rajouté un free(personne) juste pour voir.
    Il me sort alors comme résultat surprenant... "1 : Pierre, 2 : Pierre, 3 : Pierre" !!!
    Ce n'est pas parce que tu libère la mémoire que la zone est vidée. Par contre tu n'as plus le droit d'y accéder, le comportement est indéfini : ça peut très bien fonctionner normalement ou planter.

  3. #3
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 293
    Points : 4 943
    Points
    4 943
    Billets dans le blog
    5
    Par défaut
    Pour g_malloc(); tu à la fonction g_try_malloc();. Comme ca tu as un retour à NULL sans plantage.

    Pour l'allocation d'un espace de plusieurs éléments tu as aussi g_try_new();. Même comportement que la fonction précédente en cas d'échec.

    Enfin regarde les résumés des fonctions d'allocation mémoire. Tu trouveras surement ton bonheur.

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 65
    Points : 53
    Points
    53
    Par défaut
    Merci à vous pour vos réponses. Je verrai tout ça plus tard, pas le temps tout de suite.

    Citation Envoyé par gege2061 Voir le message
    Comme dans ton code, beaucoup de personne ne savent ou ne prenne pas la peine de tester le retour de malloc. Et de toutes façons pour quoi faire ?
    Pour terminer proprement ?

    Citation Envoyé par gege2061 Voir le message
    Tu n'as plus de mémoire disponible, n'espère même pas afficher une boite de dialogue. Et sous Linux le système aura déjà fait le boulot pour toi en tuant le processus qui prend le plus de mémoire.
    Pas forcément, ce n'est pas parce qu'il échoue à m'allouer une quantité monstrueuse que je lui aurais demandée qu'il n'aura pas suffisamment de mémoire pour une simple boîte de dialogue.

    Je suppose qu'en interne et en survolant le document que tu fournis, il ne fait que du g_try_malloc autrement dit du malloc à la C et pas du g_malloc.

    Là aussi, ça doit pouvoir se tester quand j'aurai plus de temps d'ici ce soir.

    D'autre part, je viens de voir qu'il y a un tuto sur le mécanisme de gestion d'erreur de la Glib ici: http://julian-ibarz.developpez.com/t.../glib/erreurs/

  5. #5
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 259
    Points : 1 633
    Points
    1 633
    Par défaut
    Citation Envoyé par vitoubien Voir le message

    Pour terminer proprement ?
    La glib termine proprement, juste de façon un peu abrupte

    Citation Envoyé par vitoubien Voir le message
    Pas forcément, ce n'est pas parce qu'il échoue à m'allouer une quantité monstrueuse que je lui aurais demandée qu'il n'aura pas suffisamment de mémoire pour une simple boîte de dialogue.
    Tu peux faire du g_try_malloc pour cette allocation monstrueuse alors. Mais quand un malloc pour une chaîne de caractère (par ex) commence à échouer, ça devient très très dur d'écrire du code correct qui fait quelque chose d'intéressant. D'où le comportement de la glib.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 65
    Points : 53
    Points
    53
    Par défaut
    Citation Envoyé par teuf13 Voir le message
    D'où le comportement de la glib.
    Oui, c'est une logique qui se tient.
    Mais là, c'est difficile de ne pas tomber dans un laisser-aller total. j'ai un peu de mal à sortir d'une discipline du tout ou rien.

  7. #7
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Points : 2 002
    Points
    2 002
    Par défaut
    Citation Envoyé par vitoubien Voir le message
    Pardon pour ce sujet un peu long et toutes ces questions mais je suis dubitatif quant à la glib pour le moment... et du coup j'ai des doutes pour GTK+ également. Mon enthousiasme premier retombe un peu.
    Bin tes erreurs sont des erreurs d'utilisation de l'API, des erreurs C dont le compilateur te prévient d'ailleurs. C'est juste que tu n'as pas encore assimilé la logique de la GLib, qui crois moi, est un des trucs les plus limpides que j'ai pu lire en C. L'API est super bien foutue et intuitive, sérieusement.

  8. #8
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Points : 2 002
    Points
    2 002
    Par défaut
    Citation Envoyé par vitoubien Voir le message
    1/ g_malloc, malloc ou g_try_malloc ?

    a/ Pourquoi utiliser g_malloc plutôt que malloc alors que j'ai lu dans la doc qu'en cas d'échec, elle ne renvoie pas NULL comme malloc mais... plante le programme ?!
    Est-ce qu'il n'ya pas une régression à utiliser g_malloc à ce niveau ?

    b/ Pourquoi alors éventuellement utiliser g_try_malloc qui semble avoir le, même comportement que malloc ?
    1.a: déjà j'aurais tendance à conseiller plutôt g_new ou g_slice_new, plus orienté objet. Ensuite, tester la valeur de retour de chaque malloc alourdit considérablement l'écriture et la lisibilité des programmes, et personne ne le fait au final. Mieux vaut quitter provoquer une erreur, sauf pour les rares cas où tu sais que tu risques de faire une allocation énorme et qui a donc des chances on négligeables d'échouer.

    1.b: question de cohésion avec le reste de l'API ? Là j'avoue que je ne sais pas trop. Peut être que la différence vient du fait que g_malloc n'agit pas sur errno.

    Citation Envoyé par vitoubien Voir le message
    2/ g_slist_free ?
    g_slist_free est sensée libérer toute la mémoire de la liste y compris les allocations nécessaires au membre "char *nom" de la structure "type_personne" ?
    Y compris quand j'alloue explicitement avec malloc pour Paul ?
    Non, comme il a été dit plus haut.

    Citation Envoyé par vitoubien Voir le message
    3/ Comportement interne en cas d'échec de malloc ?
    D'une façon générale, quel est le comportement au sein de la glib en cas d'échec d'allocation mémoire ?
    Le programme plante ? Comportement indéterminé ? Autre ? La doc ne dit rien à ce sujet.
    Je préférerais indiquer l'erreur à l'utilisateur dans l'interface graphique et terminer proprement !
    Comme dit plus haut, c'est g_error qui est appelé, qui doit déclencher une erreur fatale. Et effectivement, impossible de lancer une boite de dialogue si tu n'as plus de mémoire.

    Citation Envoyé par vitoubien Voir le message
    4/ syntaxe de GList* g_list_find(GList *list, gconstpointer data)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    GList *recherche = NULL;
    guint motif = 15;
     
    recherche = g_list_find (liste, motif);
    a/ Syntaxe ?
    A la compilation, ça plante sur les deux warnings suivants, quel est le problème ?

    warning: passing argument 1 of 'g_list_find' from incompatible pointer type
    warning: passing argument 2 of 'g_list_find' makes pointer from integer without a cast

    b/ Fonctionnement ?
    De toute façon, je ne comprends pas le fonctionnement de g_list_find. D'autant moins que je ne vois pas sur quel membre de la structure il est sensé effectuer la recherche vu qu'on ne le lui dit indique pas. Et d'autre part, il se trouve que la valeur "15" correspond à deux résultats possibles pour l'âge, quel arbitrage fait-il alors ?
    4.a : L'erreur est claire: aucun des deux arguments ne respecte le prototype. La variable liste est de type GSList dans ton programme, et tu appelles une méthode prévue pour les GList. Ensuite, le deuxième argument est un pointeur contenant la valeur à rechercher, et toi tu passes directement un entier.

    Tu ne peux rechercher que ce que tu as ajouté dans la liste. Les données que tu as ajouté à la liste sont de type "personne", alors tu ne peux rechercher que des données de type "personne", et pas des valeurs de cette structure. GList et GSList ne conservent que des pointeurs vers tes données.

    En revanche, si tu avais créé une liste d'entiers, en utilisant GINT_TO_POINTER pour pouvoir stocker les valeurs, tu aurais pu rechercher aussi des entiers.

    g_list_find se contente de retrouver ta donnée (son pointeur), il n'y a pas de recherche dans les sous-champs, tout simplement parce que tu peux y stocker n'importe quoi, pas juste des structures.

    Citation Envoyé par vitoubien Voir le message
    5/ syntaxe de gpointer g_list_nth_data(GList *list, guint n)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	personne = g_list_nth_data (liste, 1);
    Même chose, je ne comprends pas la syntaxe:
    warning: passing argument 1 of 'g_list_nth_data' from incompatible pointer type
    Toujours le même problème, tu appliques une fonction prévue pour une GList sur une GSList.

    Citation Envoyé par vitoubien Voir le message
    6/ comportement étrange
    Dans mes tests, entre chaque insertion dans la liste, j'avais rajouté un free(personne) juste pour voir.
    Il me sort alors comme résultat surprenant... "1 : Pierre, 2 : Pierre, 3 : Pierre" !!!
    La GList ne gère pas la mémoire de ce que tu y mets, elle conserve juste un pointeur vers ces éléments. Si tu essaies d'utiliser quelque chose que tu as délibérément détruit, ne t'étonne pas d'avoir des résultats bizarres...

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 65
    Points : 53
    Points
    53
    Par défaut
    Merci !
    Effectivement, je n'avais pas les yeux en face des trous ce matin et j'ai corrigé les (grossières) erreurs.

    Par contre, ce code ne fonctionne pas et je ne comprends pas pourquoi:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    	for (i = 2; i >= 0; i--)
    	{
    		recherche  = g_slist_nth (liste, i);
    		printf("age : %d\n", ((personne_type *)(recherche->data))->age);
    		printf("nom : %s\n", ((personne_type *)(recherche->data))->nom);
     
    		g_free(((personne_type *)(recherche->data))->nom);
    	}
    Et selon que j'incrémente ou que je décrémente i, je n'ai pas le même problème.

    avec for (i = 0; i < 3; i++)
    j'ai:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    age : 15
    nom : Jacques
    *** glibc detected *** /home/jf/Bureau/BUREAU/TRAVAIL/ETUDE_LANGAGES/LANGAGE_C/MES_PROGRAMMES/TEST/debug/./src/test: double free or corruption (!prev): 0x08048900 ***
    ======= Backtrace: =========
    ...
    avec for (i = 2; i >=0; i--)
    j'ai:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    age : 20
    nom : Paul
    age : 15
    nom : Pierre
    /bin/sh: line 1:  1118 Erreur de segmentation

  10. #10
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 293
    Points : 4 943
    Points
    4 943
    Billets dans le blog
    5
    Par défaut
    Sans apporter de solution ce qui saute aux yeux est que l'élement commun qui provoque l'erreur est l'élément 0, soit le premier de la liste. Comment initialises-tu ta liste?

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 65
    Points : 53
    Points
    53
    Par défaut
    @Gerald3,
    Avec g_slist_insert_sorted
    Le code d'initialisation est plus haut dans mon premier post.

  12. #12
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 293
    Points : 4 943
    Points
    4 943
    Billets dans le blog
    5
    Par défaut
    Le nom doit être alloué avec g_strdup(); par exemple.

  13. #13
    Membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 65
    Points : 53
    Points
    53
    Par défaut
    J'ai trouvé. J'avais oublié que je ne faisais pas d'allocation avec malloc pour deux des éléments de la liste mais seulement une affectation d'une chaine statique.

  14. #14
    Membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 65
    Points : 53
    Points
    53
    Par défaut
    Voici le code complet.

    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    #include <glib.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    typedef struct
    {
    	int age;
    	char *nom;
    } personne_type;
     
    int compare(personne_type *P1, personne_type *P2)
    {
    	if (P1->age > P2->age)
    		return 1;
    	else 
    		if (P1->age == P2->age)
    		{	if (P1->nom > P2->nom)
    				return 1;
    			else 
    				return -1;
    		}
    		else 
    			return -1;
    }
     
    int main (void)
    {
    	int i;
     
    	GSList *liste = NULL;
    	personne_type *personne;
     
    	GSList *recherche = NULL;
     
    	personne = g_malloc(sizeof(personne_type));
    	personne->age = 15;
    	personne->nom = g_malloc(8);
    	strcpy(personne->nom, "Jacques");
    	liste = g_slist_insert_sorted(liste, personne,
    				      (GCompareFunc)compare);
     
    	personne = g_malloc(sizeof(personne_type));
    	personne->age = 20;
    	personne->nom = g_malloc(5);
    	strcpy(personne->nom, "Paul");
     
    	liste = g_slist_insert_sorted(liste, personne,
    				      (GCompareFunc)compare);
     
    	personne2 = personne;
     
    	personne = g_malloc(sizeof(personne_type));
    	personne->age = 15;
    	personne->nom = g_malloc(7);
    	strcpy(personne->nom, "Pierre");
    	liste = g_slist_insert_sorted(liste, personne,
    				      (GCompareFunc)compare);
     
    	for (i = 0; i < 3; i++)
    	{
    		recherche  = g_slist_nth (liste, i);
    		printf("age : %d\n", ((personne_type *)(recherche->data))->age);
    		printf("nom : %s\n", ((personne_type *)(recherche->data))->nom);
     
    		g_free(((personne_type *)(recherche->data))->nom);
    	}
    		g_slist_free(liste);
     
    	return 0;
     
    }
    Mais je voudrais être sûr que tout est bien libéré correctement.

    Or Valgrind m'indique:
    14 allocs, 3 free, 4088 bytes allocated.
    24 bytes in three blocks are definitively lost in loss record 1 of 3

    Mais Valgrind n'est peut-être pas fiable ici avec g_lib. Comment le fiabiliser ?

  15. #15
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 259
    Points : 1 633
    Points
    1 633
    Par défaut
    Le code ci-dessous est plus lisible (à mon avis) et ne leake pas. C'est mieux d'utiliser g_strdup plutôt que des strcpy, ça évite des erreurs potentielles. Quand tu utilises des listes, il vaut mieux éviter comme la peste g_slist_nth car c'est très peu efficace (à chaque fois, pour retrouver le Nème élément, tu parcours toute ta liste depuis le début). Enfin, la raison de ton leak dans valgrind, c'est que tu ne libères pas la mémoire allouer pour tes personne_type.

    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
     
    #include <glib.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    typedef struct
    {
    	int age;
    	char *nom;
    } personne_type;
     
    int compare(personne_type *P1, personne_type *P2)
    {
    	if (P1->age > P2->age)
    		return 1;
    	else 
    		if (P1->age == P2->age)
    		{	if (P1->nom > P2->nom)
    				return 1;
    			else 
    				return -1;
    		}
    		else 
    			return -1;
    }
     
    static GSList *ajoute_personne(GSList *liste, const char *name, int age)
    {
    	personne_type *personne;
     
    	personne = g_malloc(sizeof(personne_type));
    	personne->age = age;
    	personne->nom = g_strdup(name);
    	return g_slist_insert_sorted(liste, personne,
    				     (GCompareFunc)compare);
    }
     
    int main (void)
    {
    	GSList *liste = NULL;
    	GSList *it;
     
    	liste = ajoute_personne (liste, "Jacques", 15);
    	liste = ajoute_personne (liste, "Paul", 20);
    	liste = ajoute_personne (liste, "Pierre", 15);
     
    	for (it = liste; it != NULL; it = it->next)
    	{
    	    	personne_type *personne;
    		personne = (personne_type *)it->data;
    		printf("age : %d\n", personne->age);
    		printf("nom : %s\n", personne->nom);
     
    		g_free(personne->nom);
    		g_free(personne);
    	}
    	g_slist_free(liste);
     
    	return 0;
    }

  16. #16
    Membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 65
    Points : 53
    Points
    53
    Par défaut
    Merci Teuf,
    en effet j'ai des progrès à faire et j'ai tiré le code sur lequel j'ai travaillé et enrichi d'un bouquin.

    J'ai rajouté dans la boucle finale,
    g_free((personne_type *)(recherche->data));
    qui satisfait valgrind.

    g_slist_free fait vraiment juste le minimum !

    Problème résolu.

  17. #17
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 259
    Points : 1 633
    Points
    1 633
    Par défaut
    g_slist_free ne peut pas deviner ce que tu as mis dans la liste. Peut être que tu as mis dedans un pointeur qu'il ne faut surtout pas libérer. Donc c'est à toi de faire ce qu'il faut

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

Discussions similaires

  1. 1 question session, 1 question syntaxe
    Par areuh_fr dans le forum Langage
    Réponses: 3
    Dernier message: 18/07/2010, 23h05
  2. Question sur un point de syntaxe
    Par Merillym dans le forum Débuter
    Réponses: 4
    Dernier message: 05/11/2009, 20h46
  3. Réponses: 1
    Dernier message: 04/05/2009, 08h31
  4. question toute simple sur la syntaxe
    Par calitom dans le forum Langage
    Réponses: 3
    Dernier message: 15/06/2006, 16h26
  5. Question de musique, question de gout
    Par blindeye dans le forum C++
    Réponses: 7
    Dernier message: 14/06/2006, 14h45

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