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 :

Erreur de Segmentation a la sortie d'une fonction appelée en CALLBACK


Sujet :

GTK+ avec C & C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 17
    Points : 21
    Points
    21
    Par défaut Erreur de Segmentation a la sortie d'une fonction appelée en CALLBACK
    Bonjour

    Je suis nouveau sur ce forum mais je pense avoir posté au bon endroit. Je travaille actuellement sur un projet en C et je rencontre un problème plutôt intrigant (en fait j'en rencontre plusieurs mais je devrais pouvoir me debrouiller avec ça). J'ai parcouru plusieurs tutoriaux et FAQ (dont celles de developpez.com). Je remercie d'ailleurs les auteurs que j'ai lu (Franck Hecht et Nicolas Joseph) cela m'a permis de bien avancer.

    Le problème que je rencontre actuellement est le suivant:
    j'appelle une fonction en appuyant sur un bouton.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    g_signal_connect (gtk_builder_get_object (p_builder, "btn_Ajout_Noeud"),"clicked", G_CALLBACK (Ajouter_Noeud),(gpointer) &Mesparametres);
    cette fonction prend en parametre le Widget et une structure de Type Params dont voici la définition

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    typedef struct Params{
        Reseau * Res;
        int * Entiers;
        /*Fenetre*/
        GtkWidget * MonWidget;
        /*permet de récuperer tous les composants*/
        GtkBuilder *build;
        /*Nom du fichier*/
        char * NomFichier;
        /*Gestion des couleurs*/
        GdkColormap *colormap;
        GdkGC * ContexteCouleur;
        GdkColor * couleurs;
    }Params;
    la fonction doit récupérer le contenu de deux champs et initialiser une structure de type Noeud.
    Ensuite la fonction remplit une boite de texte (TGtkTextView) avec les principales informations du Noeud.
    Ensuite elle vide le contenu des champs de saisie.

    J'ai modifié plusieurs fois la fonction pour contourner les problèmes de SIGABRT qui semblaient sortir de nulle part (car avant je récupérais les contenu des champs en utilisant l'event "changed").

    Maintenant la fonction se termine bien mais une fois terminée une exeption de type SIGSEV est levée (erreur de segmentation). J'ai cherché exactement ou se trouvait l'erreur en utilisant le debuggueur (et les breakpoints).

    voici les lignes issues d'un debuggage instruction par instruction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    At /home/mylee/Dossier TP/Projet/main.c:207
    In g_cclosure_marshal_VOID__VOID () (/usr/lib/libgobject-2.0.so.0)
    In g_cclosure_marshal_VOID__VOID () (/usr/lib/libgobject-2.0.so.0)
    In g_cclosure_marshal_VOID__VOID () (/usr/lib/libgobject-2.0.so.0)
    In g_cclosure_marshal_VOID__VOID () (/usr/lib/libgobject-2.0.so.0)
    In g_cclosure_marshal_VOID__VOID () (/usr/lib/libgobject-2.0.so.0)
    In g_cclosure_marshal_VOID__VOID () (/usr/lib/libgobject-2.0.so.0)
    In g_closure_invoke () (/usr/lib/libgobject-2.0.so.0)
    In g_closure_invoke () (/usr/lib/libgobject-2.0.so.0)
    In g_closure_invoke () (/usr/lib/libgobject-2.0.so.0)
    Program received signal SIGSEGV, Segmentation fault.
    In g_closure_invoke () (/usr/lib/libgobject-2.0.so.0)
    Bien entendu je n'appelle pas la foncton g_closure_invoke et g_cclosure_marshal. (je suppose qu'elle sont appelées en fin de fonction de callback.

    j'ai voulu voir le contenu de g_closure_invoke pour voir ce qui aurait pu poser problème mais je n'y ai pas accès (ce qui me semble normal étant donné que les bibliothèques sont construites).

    je vous donne le code de la fonction. Mais je ne peux pas vous joindre le code complet (le fichier main.c fait plus de 500 lignes....)

    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
    static void Ajouter_Noeud(GtkWidget * Comp,gpointer gtkPointer)
    {
        Params * Mesparams= (Params *)gtkPointer;
        GtkBuilder * Build;
        GtkWidget * txtbox;
        GtkWidget * Coord_X; //premiere boite de saisie
        GtkWidget * Coord_Y;//deuxieme boite de saisie
        int x,y;
    
        Build= (* Mesparams).build; //je récupère le gtkBuilder (j'utilise glade 3 pour générer l'interface
    /*On récupère les Objets correspondant aux boites de champ*/
        Coord_X=(GtkWidget *)gtk_builder_get_object (Build, "txt_CoordX");
        Coord_Y=(GtkWidget *)gtk_builder_get_object (Build, "txt_CoordY");
        /*fonctions de conversion standard (pas de atoi.. itoa....)*/
        x=(int)strtol(gtk_entry_get_text(GTK_ENTRY(Coord_X)),NULL,10);
        y=(int)strtol(gtk_entry_get_text(GTK_ENTRY(Coord_Y)),NULL,10);
       /*Création du Noeud*/
    
        (*((*Mesparams).Res)).Noeuds[(*Mesparams).Entiers[2]]=Creer_Noeud(x,y,(*Mesparams).Entiers[2]);
    /*Initialisation du paramètre Alpha
        (*((*Mesparams).Res)).Alpha=(*Mesparams).Entiers[5];
    /*On récupère le textview qui va indiquer le contenu des noeuds saisis*/ 
        txtbox=(GtkWidget *)gtk_builder_get_object (Build, "txt_AjoutNoeuds");
        GtkTextBuffer * MonBuff=gtk_text_view_get_buffer(GTK_TEXT_VIEW(txtbox));
        GtkTextIter debut;
        GtkTextIter fin;
        gtk_text_buffer_get_start_iter(MonBuff,&debut);
        gtk_text_buffer_get_end_iter(MonBuff,&fin);
        char *num;
        char *X;
        char *Y;
        sprintf(num,"%d",(*Mesparams).Entiers[2]);
        sprintf(X,"%d",x);
        sprintf(Y,"%d",y);
        char *texte;
    /*Récupération du contenu du textview et concaténation des nouveaux rsultats*/
        texte=gtk_text_buffer_get_text(MonBuff,&debut,&fin,FALSE);
        texte=strcat(texte," Num:");
        texte=strcat(texte,num);
        texte=strcat(texte," X:");
        texte=strcat(texte,X);
        texte=strcat(texte," Y:");
        texte=strcat(texte,Y);
        texte=strcat(texte,"||");
        gtk_text_buffer_set_text(MonBuff,texte,strlen(texte));
        gtk_text_view_set_buffer(GTK_TEXT_VIEW(txtbox),MonBuff);
       /*Vidage des champs*/
        gtk_entry_set_text(GTK_ENTRY(Coord_X),"");
        gtk_entry_set_text(GTK_ENTRY(Coord_Y),"");
        (*Mesparams).Entiers[2]++; //Incrémentation du numéro de Noeud
       
    }
    J'ai pensé que un champ de la focntion appelée pouvait etre a NULL mais en regardant le prototype de la fonction g_closure_invoke ça m'a laissé... un peu bête..

    Notes:

    Je travaille sur une machine virtuelle (virtualbox+ Debian). J'ai aussi fait un apt-get update et upgrade dans l'espoir que ce soit une erreur de version mais ça n'a rien changé.

    Je connais (un peu) d'autres langages de programmation (C#, Java, C++ (bases) ) mais le cahier des charges spécifie que cela soit fait en C.

    J'ai essayé de rendre mon message lisible et compréhensible mais étant donné que ça fait longtemps que je n'ai pas fréquenté de forums je devrai surement l'éditer pour aérer un peu.

    [EDIT] après quelques tests complémentaires, j'ai essayé en commentant la partie qui effectue le remplissage de la textView (ça fait deux jours que je suis sur le problème et je n'avais pas pensé à ça....) ainsi que le vidage des boites de dialogue et ça fonctionne. Je vais essayer de trouver quelles sont les lignes incriminées

  2. #2
    Membre éclairé
    Inscrit en
    Avril 2007
    Messages
    667
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Avril 2007
    Messages : 667
    Points : 870
    Points
    870
    Par défaut
    Salut,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
        char *texte;
        texte=gtk_text_buffer_get_text(MonBuff,&debut,&fin,FALSE);
        texte=strcat(texte," Num:");
        texte=strcat(texte,num);
        texte=strcat(texte," X:");
        texte=strcat(texte,X);
        texte=strcat(texte," Y:");
        texte=strcat(texte,Y);
        texte=strcat(texte,"||");
    gtk_text_buffer_get_text() renvoie une chaine de caracteres de taille fixe.
    Toi tu y concatenes d'autres chaines, mais la memoire allouee a texte est trop petite et tu ecris en dehors de la memoire allouee. Tu devrais agrandir texte avec realloc()

  3. #3
    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
    Tu utilises aussi sprintf de façon incorrecte, utilise plutôt g_strdup_printf pour que la mémoire où stocker la chaîne résultat soit allouée correctement. De même, utilise g_strconcat plutôt que strcat (pour les mêmes raisons d'allocation mémoire).
    Quand tu as un pointeur, tu peux utiliser
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Build= Mesparams->build;
    plutôt que

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Build= (* Mesparams).build;

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 17
    Points : 21
    Points
    21
    Par défaut
    Erf... vous avez même résolu les petits problèmes annexes que j'avais. Je vous remercie beaucoup vous m'avez retiré une sacrée épine du pied.

    J'aurais surement d'autres problèmes au cour de mon projet (notament sur l'utilisation des GTKdrawing area pour faire des dessins en couleurs) mais j'ouvrirai d'autre discussions plus tard pour faciliter les recherches sur le forum.

    Pour faciliter les recherches sur le forum j'insère aussi le nouveau code de la fonction avec les modifications (surtout avec l'utilisation des nouvelles fonctions car j'ai eu des problèmes a comprendre la documentation officielle que je parcoure depuis mes débuts avec gtk).

    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
    static void Ajouter_Noeud(GtkWidget * Comp,gpointer gtkPointer)
    {
        Params * Mesparams= (Params *)gtkPointer;
        GtkBuilder * Build;
        GtkWidget * txtbox;
        GtkWidget * Coord_X; //premiere boite de saisie
        GtkWidget * Coord_Y;//deuxieme boite de saisie
        int x,y;
    
        Build= (* Mesparams).build; //je récupère le gtkBuilder (j'utilise glade 3 pour générer l'interface
    /*On récupère les Objets correspondant aux boites de champ*/
        Coord_X=(GtkWidget *)gtk_builder_get_object (Build, "txt_CoordX");
        Coord_Y=(GtkWidget *)gtk_builder_get_object (Build, "txt_CoordY");
        /*fonctions de conversion standard (pas de atoi.. itoa....)*/
        x=(int)strtol(gtk_entry_get_text(GTK_ENTRY(Coord_X)),NULL,10);
        y=(int)strtol(gtk_entry_get_text(GTK_ENTRY(Coord_Y)),NULL,10);
       /*Création du Noeud*/
    
        (*((*Mesparams).Res)).Noeuds[(*Mesparams).Entiers[2]]=Creer_Noeud(x,y,(*Mesparams).Entiers[2]);
    /*Initialisation du paramètre Alpha
        (*((*Mesparams).Res)).Alpha=(*Mesparams).Entiers[5];
    /*On récupère le textview qui va indiquer le contenu des noeuds saisis*/ 
        txtbox=(GtkWidget *)gtk_builder_get_object (Build, "txt_AjoutNoeuds");
        GtkTextBuffer * MonBuff=gtk_text_view_get_buffer(GTK_TEXT_VIEW(txtbox));
        GtkTextIter debut;
        GtkTextIter fin;
        gtk_text_buffer_get_start_iter(MonBuff,&debut);
        gtk_text_buffer_get_end_iter(MonBuff,&fin);
        char *num;
        char *X;
        char *Y;
        char *texte;
    	/*Conversion des entiers en chaines*/
    	/*Utilisation de g_str_dup_printf*/
        /*Prototype: gchar * g_strdup_printf(format,machin a convertir);*/
        /*Le machin a convertir dependra de format*/
        X=g_strdup_printf("%d",x);
        Y=g_strdup_printf("%d",y);
        num=g_strdup_printf("%d",(*Mesparams).Entiers[2]);
    /*Récupération du contenu du textview et concaténation des nouveaux rsultats*/
        texte=gtk_text_buffer_get_text(MonBuff,&debut,&fin,FALSE);
    	/*utilisation de g_strconcat à la place de strcat*/
        texte=g_strconcat(texte," Num:",num," X:",X," Y:",Y,"||",NULL);
        gtk_text_buffer_set_text(MonBuff,texte,strlen(texte));
        gtk_text_view_set_buffer(GTK_TEXT_VIEW(txtbox),MonBuff);
    	/*Libération des ressources pour éviter les fuites de mémoire*/
        g_free(num);
        g_free(X);
        g_free(Y);
        g_free(texte);
       /*Vidage des champs*/
        gtk_entry_set_text(GTK_ENTRY(Coord_X),"");
        gtk_entry_set_text(GTK_ENTRY(Coord_Y),"");
        (*Mesparams).Entiers[2]++; //Incrémentation du numéro de Noeud
       
    }
    Le panel de fonctions GTK me semble bien fourni. On dirait presque que chaque fonction et chaque type C est repris par GTK et modifiée. Du coup a chaque manipulation est ce que le mélange de fonctions C et GTK feront bon ménage? (exemple une variable allouée avec malloc pourra elle être libérée avec g_free?)

    Il me reste encore beaucoup à apprendre.
    Merci encore

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

Discussions similaires

  1. Plusieurs variables en sortie d'une fonction
    Par Matgic95 dans le forum VB 6 et antérieur
    Réponses: 8
    Dernier message: 14/05/2008, 12h05
  2. lire la sortie d'une fonction linux
    Par NexRezzo dans le forum C
    Réponses: 2
    Dernier message: 02/12/2007, 01h08
  3. Execution a la sortie d'une fonction
    Par cococococococo dans le forum Interfaces Graphiques
    Réponses: 2
    Dernier message: 10/07/2007, 14h21
  4. Erreur PLSQL lors de l'execution d'une fonction
    Par chicken92000 dans le forum PL/SQL
    Réponses: 3
    Dernier message: 17/03/2006, 17h12

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