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 :

Plantage après plusieurs minutes


Sujet :

GTK+ avec C & C++

  1. #1
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut Plantage après plusieurs minutes
    Bonjour à tous,

    Ca fait une bonne semaine que je me casse les dents sur un code qui semble bien marcher mais qui plante ou bout de plusieurs dizaines de minutes. Ce code n'est qu'un proto pour une application plus élaborée que je compte développer.

    Grace à plusieurs échanges sur ce forum (notamment merci à liberforce..) et ailleurs, j'ai réussi à avoir une image du plantage avec gdb. Je donne ci-dessous le code, et ensuite l'état de la pile que me fourni gdb après le plantage.

    Voici d'abord le code:

    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
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <gtk/gtk.h>
     
    int flag_depart=0; /* pour le chrono */
    int flag_en_cours=0; /* pour le chrono */
    guint touche=0; /* pour la touche saisi au clavier */
    char format_sortie[500];
    gchar* sUtf8=NULL; /* pour formater des chaines de characteres */
     
    /* déclaration des widgets */
    GtkWidget *pWindow; /*fenetre principale */
    GtkWidget *pLabel; /* un label */
    GtkWidget *pTitre; /* un autre label */
    GtkWidget *pVBox; /* la box verticale */
    GtkWidget *pHBox; /* la box horizontale */
    GtkWidget *pButtonReset; /*  bouton reset */
    GtkWidget *pButtonStart; /*  bouton start */
    GtkWidget *pButtonStop; /*  bouton stop */
    GTimer *timer; /* un chronomètre */
     
    gulong handler_id; /* identifier de la connexion d'un signal (sert à la deconnexion ensuite) */
     
    int main(int argc, char **argv)
    {
        void OnDestroy(GtkWidget *pWidget, gpointer pData); /* fonction call back destroy */
        gboolean etape2(GtkWidget *widget, GdkEventKey *event, gpointer pData); /* fonction call back de recuperation d'une touche */
     
        /* Initialisation de GTK+ */
        gtk_init(&argc, &argv);
        /* création de la fenetre */
        pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        /* définition des paramètres de la fenetre */
        gtk_window_set_position(GTK_WINDOW(pWindow), GTK_WIN_POS_CENTER);
        gtk_window_set_default_size(GTK_WINDOW(pWindow), 400, 300);
        gtk_window_set_title(GTK_WINDOW(pWindow), "Testing..");
        /* création du label */
        pLabel=gtk_label_new(NULL);
        (void)sprintf(format_sortie, "<span font_desc=\"25\"><b>taper une touche\npour commencer</b></span>");
        sUtf8 = g_locale_to_utf8(format_sortie, -1, NULL, NULL, NULL);
        gtk_label_set_markup(GTK_LABEL(pLabel), sUtf8);
        /* on met le label dans la fenetre */
        gtk_container_add(GTK_CONTAINER(pWindow), pLabel);
        /* Connexion des signaux */
        g_signal_connect(G_OBJECT(pWindow), "destroy", G_CALLBACK(OnDestroy), NULL);
        handler_id=g_signal_connect(G_OBJECT (pWindow), "key_press_event", G_CALLBACK (etape2), NULL);
     
        /*affichage de la fenetre */
        gtk_widget_show_all(pWindow);
        /* Demarrage de la boucle evenementielle */
        gtk_main();
        return EXIT_SUCCESS;
    }
     
    void convertir(GTimeSpan *secondes, int *minutes, int * heures)
    {
        /* converti des secondes en heures, minutes et secondes */
        while (*secondes>59)
            {
                *minutes=*minutes+1;
                *secondes=*secondes-60;
            }
            while (*minutes>59)
            {
                *heures=*heures+1;
                *minutes=*minutes-60;
            }
    }
     
    gboolean affichage(gpointer pData)
    {
        /* Mise a jour du label */
        char tempo[1000],h[3],m[3],s[3];
        int heures=0, minutes=0;
        GTimeSpan secondes=0;
        if (flag_depart)
        {
            secondes=(GTimeSpan)g_timer_elapsed(timer, NULL);
            convertir(&secondes, &minutes, &heures);
            if (secondes>9)
                (void)sprintf(s, "%d",(int)secondes);
            else
                (void)sprintf(s, "0%d",(int)secondes);
            if (minutes>9)
                (void)sprintf(m, "%d",minutes);
            else
                (void)sprintf(m, "0%d",minutes);
            if (heures>9)
                (void)sprintf(h, "%d",heures);
            else
                (void)sprintf(h, "0%d",heures);
            (void)sprintf(tempo, "<span font_desc=\"25\"><b>%s : %s : %s (%d)</b></span>",h, m, s,touche);
            sUtf8 = g_locale_to_utf8(tempo, -1, NULL, NULL, NULL);
            gtk_label_set_markup(GTK_LABEL(pLabel), sUtf8);
        }
        return TRUE;
    }
     
    void Press_Reset(GtkButton *button, gpointer user_data)
    {
        /* reset compteur */
        char tempo[1000];
        (void)sprintf(tempo, "<span font_desc=\"25\"><b>00 : 00 : 00</b></span>");
        sUtf8 = g_locale_to_utf8(tempo, -1, NULL, NULL, NULL);
        gtk_label_set_markup(GTK_LABEL(pLabel), sUtf8);
        g_timer_start(timer);
        if (!flag_depart) g_timer_stop(timer);
        flag_en_cours=0;
    }
     
    void OnDestroy(GtkWidget *pWidget, gpointer pData)
    {
        /* Arret de la boucle evenementielle */
        g_free(sUtf8);
        gtk_main_quit();
    }
     
    void Press_Start(GtkButton *button, gpointer user_data)
    {
        /* start compteur */
        if (!flag_depart)
        {
            if (!flag_en_cours)
                g_timer_start(timer);
            else
                g_timer_continue(timer);
        }
        flag_depart=1;
    }
     
    void Press_Stop(GtkButton *button, gpointer user_data)
    {
        /* stop compteur */
        g_timer_stop(timer);
        flag_depart=0;
        flag_en_cours=1;
    }
     
    gboolean recup_key(GtkWidget *window, GdkEventKey *event, gpointer data)
    {
        /* recuperer la valeur de la touche saisie */
        touche=event->keyval;
        return TRUE;
    }
     
    gboolean etape2(GtkWidget *window, GdkEventKey *event, gpointer data)
    {
        /* fin de l'étape 1 et lancement de l'étape 2 */
        /* création de la box verticale */
        pVBox = gtk_vbox_new(FALSE, 0);
        /* création de la box horizontale */
        pHBox = gtk_hbox_new(TRUE, 0);
        /* on détruit le label (ce qui permet - entre autre de l'enlever de son container) */
        gtk_widget_destroy(pLabel);
        /* et on le recrée */
        pLabel=gtk_label_new(NULL);
        (void)sprintf(format_sortie, "<span font_desc=\"25\"><b>00 : 00 : 00</b></span>");
        sUtf8 = g_locale_to_utf8(format_sortie, -1, NULL, NULL, NULL);
        gtk_label_set_markup(GTK_LABEL(pLabel), sUtf8);
        /* création du titre */
        pTitre=gtk_label_new(NULL);
        (void)sprintf(format_sortie, "<span font_desc=\"15\" background=\"#000000\" foreground=\"#FFFFFF\"><b>Testing..</b></span>");
        sUtf8 = g_locale_to_utf8(format_sortie, -1, NULL, NULL, NULL);
        gtk_label_set_markup(GTK_LABEL(pTitre), sUtf8);
        /* création du bouton reset */
        pButtonReset = gtk_button_new_with_label("Reset");
        /* création du bouton start */
        pButtonStart = gtk_button_new_with_label("Start");
        /* création du bouton stop */
        pButtonStop = gtk_button_new_with_label("Stop");
        /* création du timer */
        timer=g_timer_new();
        g_timer_stop(timer);
        /* AJout du titre dans la GtkVBox */
        gtk_box_pack_start(GTK_BOX(pVBox), pTitre, FALSE, TRUE, 10);
        /* Ajout des boutons reset, start dans la GtkHBox */
        gtk_box_pack_start(GTK_BOX(pHBox), pButtonStart, FALSE, TRUE, 0);
        gtk_box_pack_start(GTK_BOX(pHBox), pButtonStop, FALSE, TRUE, 0);
        gtk_box_pack_start(GTK_BOX(pHBox), pButtonReset, FALSE, TRUE, 0);
        /* ajout de la boite horizontale dans la boite verticale */
        gtk_box_pack_start(GTK_BOX(pVBox), pHBox, FALSE, TRUE, 0);
        /* ajout du label dans la GtkVBox */
        gtk_box_pack_start(GTK_BOX(pVBox), pLabel, TRUE, TRUE, 0);
        /* ajout de la GtkVBox à la fenetre */
        gtk_container_add(GTK_CONTAINER(pWindow), pVBox);
        /* modification de la taille de la fenêtre */
        gtk_window_resize(GTK_WINDOW(pWindow), 300, 100);
        /* deconnexion du signal capturé en étape 1 */
        g_signal_handler_disconnect(GTK_WINDOW(pWindow),handler_id);
        /* Connexion des autres signaux */
        g_signal_connect (G_OBJECT (pWindow), "key_press_event", G_CALLBACK (recup_key), NULL);
        g_signal_connect(G_OBJECT(pButtonStart),"pressed", G_CALLBACK(Press_Start), NULL);
        g_signal_connect(G_OBJECT(pButtonStop),"pressed", G_CALLBACK(Press_Stop), NULL);
        g_signal_connect(G_OBJECT(pButtonReset),"pressed", G_CALLBACK(Press_Reset), NULL);
        /* fonction appelée régulièrement .. */
        g_timeout_add ((guint)1, affichage,NULL);
        /* et on raffiche tout */
        gtk_widget_show_all(pWindow);
        return TRUE;
    }
    et l'état de la pile:

    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
    Child process PID: 2888
     
    [debug][New Thread 2888.0x15a4]
    [debug][New Thread 2888.0xfe8]
    [debug][New Thread 2888.0xac8]
    [debug][New Thread 2888.0x17a4]
    [debug][New Thread 2888.0xb9c]
    [debug][New Thread 2888.0xbd8]
    [debug]Program received signal SIGSEGV, Segmentation fault.
    [debug]0x68de05bd in cairo_image_surface_get_data () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libcairo-2.dll
    [debug]>>>>>>cb_gdb:
     
    Program received signal SIGSEGV, Segmentation fault.
    In cairo_image_surface_get_data () (C:\Program Files (x86)\CodeBlocks\gtk\bin\libcairo-2.dll)
     
    [debug]> bt 30
    [debug]#0  0x68de05bd in cairo_image_surface_get_data () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libcairo-2.dll
    [debug]#1  0x6c38d268 in _gdk_pixmap_new () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libgdk-win32-2.0-0.dll
    [debug]#2  0x6c35f694 in gdk_window_process_updates_internal () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libgdk-win32-2.0-0.dll
    [debug]#3  0x6c361497 in gdk_window_process_all_updates () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libgdk-win32-2.0-0.dll
    [debug]#4  0x617d5271 in gtk_container_idle_sizer () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libgtk-win32-2.0-0.dll
    [debug]#5  0x6c34137c in gdk_threads_dispatch () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libgdk-win32-2.0-0.dll
    [debug]#6  0x685eb167 in g_main_context_dispatch () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libglib-2.0-0.dll
    [debug]#7  0x685eb90d in g_main_context_iterate.clone.5 () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libglib-2.0-0.dll
    [debug]#8  0x685ebd9d in g_main_loop_run () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libglib-2.0-0.dll
    [debug]#9  0x61859038 in gtk_main () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libgtk-win32-2.0-0.dll
    [debug]#10 0x00401549 in main (argc=1, argv=0x574d28) at D:\calcul C\essai gtk\essai gtk\essai 2\main.c:54
    [debug]>>>>>>cb_gdb:
    [debug]> frame 10
    [debug]#10 0x00401549 in main (argc=1, argv=0x574d28) at D:\calcul C\essai gtk\essai gtk\essai 2\main.c:54
    [debug]__D:\calcul C\essai gtk\essai gtk\essai 2\main.c:54:2260:beg:0x401549
    [debug]>>>>>>cb_gdb:
     
    #10 0x00401549 in main (argc=1, argv=0x574d28) at D:\calcul C\essai gtk\essai gtk\essai 2\main.c:54
    __D:\calcul C\essai gtk\essai gtk\essai 2\main.c:54:2260:beg:0x401549
    At D:\calcul C\essai gtk\essai gtk\essai 2\main.c:54
     
    [debug]> bt 30
    [debug]#0  0x68de05bd in cairo_image_surface_get_data () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libcairo-2.dll
    [debug]#1  0x6c38d268 in _gdk_pixmap_new () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libgdk-win32-2.0-0.dll
    [debug]#2  0x6c35f694 in gdk_window_process_updates_internal () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libgdk-win32-2.0-0.dll
    [debug]#3  0x6c361497 in gdk_window_process_all_updates () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libgdk-win32-2.0-0.dll
    [debug]#4  0x617d5271 in gtk_container_idle_sizer () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libgtk-win32-2.0-0.dll
    [debug]#5  0x6c34137c in gdk_threads_dispatch () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libgdk-win32-2.0-0.dll
    [debug]#6  0x685eb167 in g_main_context_dispatch () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libglib-2.0-0.dll
    [debug]#7  0x685eb90d in g_main_context_iterate.clone.5 () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libglib-2.0-0.dll
    [debug]#8  0x685ebd9d in g_main_loop_run () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libglib-2.0-0.dll
    [debug]#9  0x61859038 in gtk_main () from C:\Program Files (x86)\CodeBlocks\gtk\bin\libgtk-win32-2.0-0.dll
    [debug]#10 0x00401549 in main (argc=1, argv=0x574d28) at D:\calcul C\essai gtk\essai gtk\essai 2\main.c:54
    [debug]>>>>>>cb_gdb:
    [debug]> frame 10
    [debug]#10 0x00401549 in main (argc=1, argv=0x574d28) at D:\calcul C\essai gtk\essai gtk\essai 2\main.c:54
    [debug]__D:\calcul C\essai gtk\essai gtk\essai 2\main.c:54:2260:beg:0x401549
    [debug]>>>>>>cb_gdb:
     
    #10 0x00401549 in main (argc=1, argv=0x574d28) at D:\calcul C\essai gtk\essai gtk\essai 2\main.c:54
    __D:\calcul C\essai gtk\essai gtk\essai 2\main.c:54:2260:beg:0x401549
    (je précise que j'ai viré deux lignes de commentaires en début de code, du coup, par exemple, la ligne 54 spécifiée dans les sortie de gdb, correspond au gtk_main())

    Il semble que le plantage se fasse lors de l'appel de la fonction cairo_image_surface_get_data() de la library cairo, mais je n'utilise pas cette library. gtk l'utilise donc à mon insu et génère - à l'occasion - un plantage.

    Je suis vraiment à court d'idée et une aide serait vraiment la bienvenue.

    D'avance merci, Eric.

  2. #2
    Membre confirmé
    Profil pro
    Retraité
    Inscrit en
    Novembre 2009
    Messages
    330
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2009
    Messages : 330
    Points : 607
    Points
    607
    Par défaut
    Bonjour,

    J'ai essayé de compiler et exécuter ton code (sous Linux et GTK+2) et j'ai constaté, en examinant ce qui se passait avec le moniteur système, deux choses:
    il occupe 100% d'un CPU,
    mais surtout, il y a une fuite de mémoire et le programme va planter quand il n'a plus assez de place.
    Cette fuite est due à g_locale_to_utf8() qui crée à chaque appel une nouvelle chaîne de caractères, chaîne que tu ne libère pas après usage.

    En rajoutant g_free (sUtf8), la fuite de mémoire disparait, donc le programme ne doit plus planter (je n'ai pas attendu, mais la taille mémoire reste stable...).

    Par contre la méthode employée ne me semble pas très pertinente car employer toute une CPU pour compter des secondes, c'est pas terrible...
    Il me semble que liberforce, qui est bien plus compétent que moi en la matière, a déjà donné dans ce forum de bon conseils à ce sujet.

  3. #3
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    Citation Envoyé par pvincent Voir le message
    Bonjour,

    J'ai essayé de compiler et exécuter ton code (sous Linux et GTK+2) et j'ai constaté, en examinant ce qui se passait avec le moniteur système, deux choses:
    il occupe 100% d'un CPU,
    mais surtout, il y a une fuite de mémoire et le programme va planter quand il n'a plus assez de place.
    Cette fuite est due à g_locale_to_utf8() qui crée à chaque appel une nouvelle chaîne de caractères, chaîne que tu ne libère pas après usage.

    En rajoutant g_free (sUtf8), la fuite de mémoire disparait, donc le programme ne doit plus planter (je n'ai pas attendu, mais la taille mémoire reste stable...).


    Par contre la méthode employée ne me semble pas très pertinente car employer toute une CPU pour compter des secondes, c'est pas terrible...
    Il me semble que liberforce, qui est bien plus compétent que moi en la matière, a déjà donné dans ce forum de bon conseils à ce sujet.
    Merci, mais cette réponse m'étonne, car - soupçonnant un problème avec g_locale_to_utf8() effectivement - j'ai refais tourner le même code sans plus aucune utilisation de g_locale_to_utf8() (et de sUtf8) et je tombe sur le même plantage.. Par ailleurs, en suivant la valeur de sUtf8 avec un debugger, celle-ci reste correcte (même si elle est recréée à chaque fois), et je ne vois pas pourquoi il y aurait une fuite mémoire à ce niveau.. Enfin, de mon côté, aucun comportement bizarre sur le moniteur système (windows 7).

    Pour la méthode employée, j'ai dit que ce code était un proto, en fait le but final n'est pas de compter les secondes mais de lire un flux de donnée en continue, ce que je fais ici avec la résolution la plus fine, la milliseconde.

    Je reste preneur d'avis sur ce point. En tout cas, merci pour votre temps,

    Eric.

  4. #4
    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
    Bon, j'ai vu qu'on parlait de moi, j'ai vu le bat-signal dans le signal, alors je suis venu .

    Pour g_locale_to_utf8, je confirme qu'il y a une fuite mémoire à tous les appels, puisque tu ne libères pas la chaîne après l'avoir utilisée. Si le pointeur change, c'est parce que tu alloues un nouveau bout de mémoire. Si tu n'as pas libéré l'ancien avant cela, tu perds la trace de l'ancienne mémoire allouée, et tu as donc une fuite (les quelques octets de ta chaîne toutes les millisecondes).

    Pour le 100% de CPU, tu dois te douter que c'est à cause de l'appel à g_timeout_add, qui demande à appeler la callback toutes les millisecondes, soit 1000 fois par secondes. Ce n'est pas pertinent pour un timer, même si je comprends que ce n'est qu'un exercice pour toi.

    En plus, ton appel à g_timeout_add se fait dans ta fonction etape2, déclenchée dès l'appui d'une touche. Tu commences donc à bouffer 100% du CPU à ce moment là, que le timer tourne ou pas. Bug ou pas ? Si tu programmes un chronomètre, oui, si tu programmes ton application finale, aucune idée. Mais si c'est pour lire des données "au fil de l'eau", le polling tel que tu le fais n'est une bonne idée. Le polling est rarement une bonne idée. Je dirais plutôt qu'il faut jeter un coup d'oeil aux GIOStream, voire aux GSource selon les cas.

    Conclusion: tu codes une application alors que tu veux en faire une autre. Du coup c'est difficile de te conseiller pour faire un truc propre, parce qu'on ne comprend pas ce que tu veux réaliser. Donc je te conseille sincèrement de réorienter ton application dans un sens ou dans l'autre, pour coder soit un vrai timer, soit ta vraie application, mais pas un truc bâtard entre les deux, parce que nous ne pouvons pas distinguer un bug d'un truc que tu as fait exprès en ayant ton autre application en tête.

    Pour l'exemple (ça faisait un moment que j'y pensais), j'ai transformé ton code pour avoir juste un chronomètre.

    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
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
     
    #include <stdlib.h>  /* pour EXIT_SUCCESS */
    #include <gtk/gtk.h>
     
     
    typedef struct
    {
    	GtkWidget *window;
    	GtkWidget *label;
    	GtkWidget *reset;
    	GtkWidget *start;
    	GtkWidget *stop;
    } Gui;
     
    gboolean is_running = FALSE;
    GTimer *timer = NULL; /* un chronomètre */
     
    /* Decoupe un temps exprimé en double en heures, minutes et secondes */
    void split_time (double time, int *hours, int *minutes, int *seconds)
    {
    	gint64 t = (gint64) time;
    	*hours = t / 3600;
    	*minutes = t / 60;
    	*seconds = t % 60;
    }
     
    void update_time_label (GtkWidget *label, double time)
    {
    	int hours = 0, minutes = 0, seconds = 0;
    	gchar *sUtf8;
    	gchar *message;
     
    	split_time (time, &hours, &minutes, &seconds);
    	message = g_strdup_printf ("<span font_desc=\"25\"><b>"
    			"%02d : %02d : %02d"
    			"</b></span>",
    			hours, minutes, seconds);
    	sUtf8 = g_locale_to_utf8 (message, -1, NULL, NULL, NULL);
    	gtk_label_set_markup (GTK_LABEL(label), sUtf8);
    	g_free (sUtf8);
    	g_free (message);
    }
     
    gboolean on_timeout (gpointer user_data)
    {
    	GtkWidget *label = user_data;
    	update_time_label (label, g_timer_elapsed (timer, NULL));
    	return is_running; /* détermine si la callback doit être rappelée */
    }
     
    void on_destroy (G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED gpointer user_data)
    {
    	gtk_main_quit();
    }
     
    void on_reset (G_GNUC_UNUSED GtkButton *button, gpointer user_data)
    {
    	GtkWidget *label = user_data;
     
    	/* Contourner g_timer_reset qui marche mal 
    	 * (renvoie parfois des valeurs négatives ensuite) */
    	g_timer_start (timer);
    	if (! is_running)
    		g_timer_stop (timer);
    	update_time_label (label, g_timer_elapsed (timer, NULL));
    }
     
    void on_start (G_GNUC_UNUSED GtkButton *button, gpointer user_data)
    {
    	GtkLabel *label = user_data;
     
    	if (! is_running)
    	{
    		if G_UNLIKELY (timer == NULL)
    			timer = g_timer_new ();
    		else
    			g_timer_continue (timer);
    		g_timeout_add (200, on_timeout, label);
    		is_running = TRUE;
    	}
    }
     
    void on_stop (G_GNUC_UNUSED GtkButton *button, G_GNUC_UNUSED gpointer user_data)
    {
    	g_timer_stop (timer);
    	is_running = FALSE;
    }
     
    int main (int argc, char **argv)
    {
    	gtk_init(&argc, &argv);
     
    	/* Création de la fenetre principale */
    	Gui *gui = g_new0 (Gui, 1);
    	gui->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    	gtk_window_set_position (GTK_WINDOW (gui->window), GTK_WIN_POS_CENTER);
    	gtk_window_set_default_size (GTK_WINDOW (gui->window), 300, 100);
    	gtk_window_set_title (GTK_WINDOW (gui->window), "Stop Watch");
     
    	/* Création des autres widgets */
    	GtkWidget *pVBox = gtk_vbox_new (FALSE, 0);
    	GtkWidget *pHBox = gtk_hbox_new (TRUE, 0);
    	gui->label = gtk_label_new (NULL);
    	gui->reset = gtk_button_new_with_label ("Reset");
    	gui->start = gtk_button_new_with_label ("Start");
    	gui->stop = gtk_button_new_with_label ("Stop");
     
    	/* Création de l'arborescence de widgets */
    	gtk_container_add (GTK_CONTAINER (gui->window), pVBox);
    	gtk_box_pack_start (GTK_BOX (pVBox), gui->label, TRUE, TRUE, 0);
    	gtk_box_pack_start (GTK_BOX (pVBox), pHBox, FALSE, TRUE, 0);
    	gtk_box_pack_start (GTK_BOX (pHBox), gui->start, FALSE, TRUE, 0);
    	gtk_box_pack_start (GTK_BOX (pHBox), gui->stop, FALSE, TRUE, 0);
    	gtk_box_pack_start (GTK_BOX (pHBox), gui->reset, FALSE, TRUE, 0);
     
    	/* Initialisation du temps affiché pour le chronomètre */
    	update_time_label (gui->label, 0.0);
     
    	/* Connexion des signaux */
    	g_signal_connect (G_OBJECT (gui->window), "destroy", G_CALLBACK (on_destroy), NULL);
    	g_signal_connect (G_OBJECT (gui->start), "pressed", G_CALLBACK (on_start), gui->label);
    	g_signal_connect (G_OBJECT (gui->stop), "pressed", G_CALLBACK (on_stop), gui->label);
    	g_signal_connect (G_OBJECT (gui->reset),"pressed", G_CALLBACK (on_reset), gui->label);
     
    	/* Affichage et lancement de l'application */
    	gtk_widget_show_all (gui->window);
    	gtk_main();
    	return EXIT_SUCCESS;
    }

  5. #5
    Membre confirmé
    Profil pro
    Retraité
    Inscrit en
    Novembre 2009
    Messages
    330
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2009
    Messages : 330
    Points : 607
    Points
    607
    Par défaut
    Liberforce est le meilleur...
    Juste une petite remarque: pour que le compteur de minutes se remette à zéro à chaque nouvelle heure, dans split_time(), il faut retrancher *hours * 60 à *minutes.

  6. #6
    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
    Arf, effectivement il y a une coquille. On la refait en plus propre.

    Il faut en effet faire comme si on extrayait les chiffres d'un nombre, avec des modulos et divisions successives.
    Exemple: si on a 123456 en base 10,
    123456 modulo 10 → 6
    123456 / 10 → 12345
    12345 modulo 10 → 5
    12345 / 10 → 1234
    1234 modulo 10 → 4
    1234 / 10 → 123
    123 modulo 10 → 3
    123 / 10 → 12
    12 modulo 10 → 2
    12 / 10 → 1
    1 modulo 10 → 1
    1 / 10 → 0

    Là le principe est le même, sauf que les secondes sont en base 60, les minutes aussi, et les heures sont en base 24. Les heures retomberont à 0 après 24 heures grâce au modulo.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void split_time (double time, int *hours, int *minutes, int *seconds)
    {
    	gint64 t = (gint64) time;
    	*seconds = t % 60;
    	t /= 60;
    	*minutes = t % 60;
    	t /= 60;
    	*hours = t % 24;
    }
    Ce qui donne au final:
    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
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
     
    #include <stdlib.h>  /* pour EXIT_SUCCESS */
    #include <gtk/gtk.h>
     
     
    typedef struct
    {
    	GtkWidget *window;
    	GtkWidget *label;
    	GtkWidget *reset;
    	GtkWidget *start;
    	GtkWidget *stop;
    } Gui;
     
    gboolean is_running = FALSE;
    GTimer *timer = NULL; /* un chronomètre */
     
    /* Decoupe un temps exprimé en double en heures, minutes et secondes */
    void split_time (double time, int *hours, int *minutes, int *seconds)
    {
    	gint64 t = (gint64) time;
    	*seconds = t % 60;
    	t /= 60;
    	*minutes = t % 60;
    	t /= 60;
    	*hours = t % 24;
    }
     
    void update_time_label (GtkWidget *label, double time)
    {
    	int hours = 0, minutes = 0, seconds = 0;
    	gchar *sUtf8;
    	gchar *message;
     
    	split_time (time, &hours, &minutes, &seconds);
    	message = g_strdup_printf ("<span font_desc=\"25\"><b>"
    			"%02d : %02d : %02d"
    			"</b></span>",
    			hours, minutes, seconds);
    	sUtf8 = g_locale_to_utf8 (message, -1, NULL, NULL, NULL);
    	gtk_label_set_markup (GTK_LABEL(label), sUtf8);
    	g_free (sUtf8);
    	g_free (message);
    }
     
    gboolean on_timeout (gpointer user_data)
    {
    	GtkWidget *label = user_data;
    	update_time_label (label, g_timer_elapsed (timer, NULL));
    	return is_running; /* détermine si la callback doit être rappelée */
    }
     
    void on_destroy (G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED gpointer user_data)
    {
    	gtk_main_quit();
    }
     
    void on_reset (G_GNUC_UNUSED GtkButton *button, gpointer user_data)
    {
    	GtkWidget *label = user_data;
     
    	/* Contourner g_timer_reset qui marche mal 
    	 * (renvoie parfois des valeurs négatives ensuite) */
    	g_timer_start (timer);
    	if (! is_running)
    		g_timer_stop (timer);
    	update_time_label (label, g_timer_elapsed (timer, NULL));
    }
     
    void on_start (G_GNUC_UNUSED GtkButton *button, gpointer user_data)
    {
    	GtkLabel *label = user_data;
     
    	if (! is_running)
    	{
    		if G_UNLIKELY (timer == NULL)
    			timer = g_timer_new ();
    		else
    			g_timer_continue (timer);
    		g_timeout_add (200, on_timeout, label);
    		is_running = TRUE;
    	}
    }
     
    void on_stop (G_GNUC_UNUSED GtkButton *button, G_GNUC_UNUSED gpointer user_data)
    {
    	g_timer_stop (timer);
    	is_running = FALSE;
    }
     
    int main (int argc, char **argv)
    {
    	gtk_init(&argc, &argv);
     
    	/* Création de la fenetre principale */
    	Gui *gui = g_new0 (Gui, 1);
    	gui->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    	gtk_window_set_position (GTK_WINDOW (gui->window), GTK_WIN_POS_CENTER);
    	gtk_window_set_default_size (GTK_WINDOW (gui->window), 300, 100);
    	gtk_window_set_title (GTK_WINDOW (gui->window), "Stop Watch");
     
    	/* Création des autres widgets */
    	GtkWidget *pVBox = gtk_vbox_new (FALSE, 0);
    	GtkWidget *pHBox = gtk_hbox_new (TRUE, 0);
    	gui->label = gtk_label_new (NULL);
    	gui->reset = gtk_button_new_with_label ("Reset");
    	gui->start = gtk_button_new_with_label ("Start");
    	gui->stop = gtk_button_new_with_label ("Stop");
     
    	/* Création de l'arborescence de widgets */
    	gtk_container_add (GTK_CONTAINER (gui->window), pVBox);
    	gtk_box_pack_start (GTK_BOX (pVBox), gui->label, TRUE, TRUE, 0);
    	gtk_box_pack_start (GTK_BOX (pVBox), pHBox, FALSE, TRUE, 0);
    	gtk_box_pack_start (GTK_BOX (pHBox), gui->start, FALSE, TRUE, 0);
    	gtk_box_pack_start (GTK_BOX (pHBox), gui->stop, FALSE, TRUE, 0);
    	gtk_box_pack_start (GTK_BOX (pHBox), gui->reset, FALSE, TRUE, 0);
     
    	/* Initialisation du temps affiché pour le chronomètre */
    	update_time_label (gui->label, 0.0);
     
    	/* Connexion des signaux */
    	g_signal_connect (G_OBJECT (gui->window), "destroy", G_CALLBACK (on_destroy), NULL);
    	g_signal_connect (G_OBJECT (gui->start), "pressed", G_CALLBACK (on_start), gui->label);
    	g_signal_connect (G_OBJECT (gui->stop), "pressed", G_CALLBACK (on_stop), gui->label);
    	g_signal_connect (G_OBJECT (gui->reset),"pressed", G_CALLBACK (on_reset), gui->label);
     
    	/* Affichage et lancement de l'application */
    	gtk_widget_show_all (gui->window);
    	gtk_main();
    	return EXIT_SUCCESS;
    }

  7. #7
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    Citation Envoyé par liberforce Voir le message
    Bon, j'ai vu qu'on parlait de moi, j'ai vu le bat-signal dans le signal, alors je suis venu .

    Pour g_locale_to_utf8, je confirme qu'il y a une fuite mémoire à tous les appels, puisque tu ne libères pas la chaîne après l'avoir utilisée. Si le pointeur change, c'est parce que tu alloues un nouveau bout de mémoire. Si tu n'as pas libéré l'ancien avant cela, tu perds la trace de l'ancienne mémoire allouée, et tu as donc une fuite (les quelques octets de ta chaîne toutes les millisecondes).

    Pour le 100% de CPU, tu dois te douter que c'est à cause de l'appel à g_timeout_add, qui demande à appeler la callback toutes les millisecondes, soit 1000 fois par secondes. Ce n'est pas pertinent pour un timer, même si je comprends que ce n'est qu'un exercice pour toi.

    En plus, ton appel à g_timeout_add se fait dans ta fonction etape2, déclenchée dès l'appui d'une touche. Tu commences donc à bouffer 100% du CPU à ce moment là, que le timer tourne ou pas. Bug ou pas ? Si tu programmes un chronomètre, oui, si tu programmes ton application finale, aucune idée. Mais si c'est pour lire des données "au fil de l'eau", le polling tel que tu le fais n'est une bonne idée. Le polling est rarement une bonne idée. Je dirais plutôt qu'il faut jeter un coup d'oeil aux GIOStream, voire aux GSource selon les cas.

    Conclusion: tu codes une application alors que tu veux en faire une autre. Du coup c'est difficile de te conseiller pour faire un truc propre, parce qu'on ne comprend pas ce que tu veux réaliser. Donc je te conseille sincèrement de réorienter ton application dans un sens ou dans l'autre, pour coder soit un vrai timer, soit ta vraie application, mais pas un truc bâtard entre les deux, parce que nous ne pouvons pas distinguer un bug d'un truc que tu as fait exprès en ayant ton autre application en tête.

    Pour l'exemple (ça faisait un moment que j'y pensais), j'ai transformé ton code pour avoir juste un chronomètre.

    [...]
    Merci!

    Il ne fait aucun doute que cette réponse m'aide et me fait progresser. Très pédagogique (et je me considère encore en phase d'apprentissage pour l'utilisation de GTK). Cependant, même si je comprends mieux plusieurs choses, il reste des points encore à résoudre.

    En fait, il y a deux choses dans ces échanges, qui sont indépendantes je pense:

    1) Les fuites supposées de mémoire avec g_locale_to_utf8(), et
    2) Le choix d'un appel trop fréquent à une fonction callback avec g_timeout_add().

    Pour le point 1:

    Je reste pas trop convaincu par cette histoire de fuite mémoire. Pour en avoir le coeur nette, j'ai donc repris le même code et ai mis des g_free() aux bons endroits. Je retombe sur le même plantage ou bout de plusieurs dizaines de minutes (entre une heure et deux heures sur ma machine). Je reste convaincu qu'il y a un autre problème. Et je continues à ne pas comprendre lequel (et reste preneur d'une idée). C'est pas magique tout de même, il doit bien y avoir une explication! Notamment, pourquoi l'état de la pile de gdb au plantage pointe toujours vers cette appel à cairo_image_surface_get_data() de la library cairo que je n'utilise pas? Ca reste énigmatique..

    Voici le code modifié pour info:

    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
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <gtk/gtk.h>
     
    int flag_depart=0; /* pour le chrono */
    int flag_en_cours=0; /* pour le chrono */
    guint touche=0; /* pour la touche saisi au clavier */
    char format_sortie[500];
     
    /* déclaration des widgets */
    GtkWidget *pWindow; /*fenetre principale */
    GtkWidget *pLabel; /* un label */
    GtkWidget *pTitre; /* un autre label */
    GtkWidget *pVBox; /* la box verticale */
    GtkWidget *pHBox; /* la box horizontale */
    GtkWidget *pButtonReset; /*  bouton reset */
    GtkWidget *pButtonStart; /*  bouton start */
    GtkWidget *pButtonStop; /*  bouton stop */
    GTimer *timer; /* un chronomètre */
     
    gulong handler_id; /* identifier de la connexion d'un signal (sert à la deconnexion ensuite) */
     
    int main(int argc, char **argv)
    {
        gchar* sUtf8=NULL; /* pour formater des chaines de characteres */
        void OnDestroy(GtkWidget *pWidget, gpointer pData); /* fonction call back destroy */
        gboolean etape2(GtkWidget *widget, GdkEventKey *event, gpointer pData); /* fonction call back de recuperation d'une touche */
     
        /* Initialisation de GTK+ */
        gtk_init(&argc, &argv);
        /* création de la fenetre */
        pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        /* définition des paramètres de la fenetre */
        gtk_window_set_position(GTK_WINDOW(pWindow), GTK_WIN_POS_CENTER);
        gtk_window_set_default_size(GTK_WINDOW(pWindow), 400, 300);
        gtk_window_set_title(GTK_WINDOW(pWindow), "Testing..");
        /* création du label */
        pLabel=gtk_label_new(NULL);
        (void)sprintf(format_sortie, "<span font_desc=\"25\"><b>taper une touche\npour commencer</b></span>");
        sUtf8 = g_locale_to_utf8(format_sortie, -1, NULL, NULL, NULL);
        gtk_label_set_markup(GTK_LABEL(pLabel), sUtf8);
        g_free(sUtf8);
        /* on met le label dans la fenetre */
        gtk_container_add(GTK_CONTAINER(pWindow), pLabel);
        /* Connexion des signaux */
        g_signal_connect(G_OBJECT(pWindow), "destroy", G_CALLBACK(OnDestroy), NULL);
        handler_id=g_signal_connect(G_OBJECT (pWindow), "key_press_event", G_CALLBACK (etape2), NULL);
     
        /*affichage de la fenetre */
        gtk_widget_show_all(pWindow);
        /* Demarrage de la boucle evenementielle */
        gtk_main();
        return EXIT_SUCCESS;
    }
     
    void convertir(GTimeSpan *secondes, int *minutes, int * heures)
    {
        /* converti des secondes en heures, minutes et secondes */
        while (*secondes>59)
            {
                *minutes=*minutes+1;
                *secondes=*secondes-60;
            }
            while (*minutes>59)
            {
                *heures=*heures+1;
                *minutes=*minutes-60;
            }
    }
     
    gboolean affichage(gpointer pData)
    {
        /* Mise a jour du label */
        char tempo[1000],h[3],m[3],s[3];
        int heures=0, minutes=0;
        GTimeSpan secondes=0;
        gchar* sUtf8=NULL; /* pour formater des chaines de characteres */
        if (flag_depart)
        {
            secondes=(GTimeSpan)g_timer_elapsed(timer, NULL);
            convertir(&secondes, &minutes, &heures);
            if (secondes>9)
                (void)sprintf(s, "%d",(int)secondes);
            else
                (void)sprintf(s, "0%d",(int)secondes);
            if (minutes>9)
                (void)sprintf(m, "%d",minutes);
            else
                (void)sprintf(m, "0%d",minutes);
            if (heures>9)
                (void)sprintf(h, "%d",heures);
            else
                (void)sprintf(h, "0%d",heures);
            (void)sprintf(tempo, "<span font_desc=\"25\"><b>%s : %s : %s (%d)</b></span>",h, m, s,touche);
           sUtf8 = g_locale_to_utf8(tempo, -1, NULL, NULL, NULL);
           gtk_label_set_markup(GTK_LABEL(pLabel), sUtf8);
        }
        g_free(sUtf8);
        return TRUE;
    }
     
    void Press_Reset(GtkButton *button, gpointer user_data)
    {
        /* reset compteur */
        char tempo[1000];
        gchar* sUtf8=NULL; /* pour formater des chaines de characteres */
        (void)sprintf(tempo, "<span font_desc=\"25\"><b>00 : 00 : 00</b></span>");
        sUtf8 = g_locale_to_utf8(tempo, -1, NULL, NULL, NULL);
        gtk_label_set_markup(GTK_LABEL(pLabel), sUtf8);
        g_free(sUtf8);
        g_timer_start(timer);
        if (!flag_depart) g_timer_stop(timer);
        flag_en_cours=0;
    }
     
    void OnDestroy(GtkWidget *pWidget, gpointer pData)
    {
        /* Arret de la boucle evenementielle */
        gtk_main_quit();
    }
     
    void Press_Start(GtkButton *button, gpointer user_data)
    {
        /* start compteur */
        if (!flag_depart)
        {
            if (!flag_en_cours)
                g_timer_start(timer);
            else
                g_timer_continue(timer);
        }
        flag_depart=1;
    }
     
    void Press_Stop(GtkButton *button, gpointer user_data)
    {
        /* stop compteur */
        g_timer_stop(timer);
        flag_depart=0;
        flag_en_cours=1;
    }
     
    gboolean recup_key(GtkWidget *window, GdkEventKey *event, gpointer data)
    {
        /* recuperer la valeur de la touche saisie */
        touche=event->keyval;
        return TRUE;
    }
     
    gboolean etape2(GtkWidget *window, GdkEventKey *event, gpointer data)
    {
        /* fin de l'étape 1 et lancement de l'étape 2 */
        gchar* sUtf8=NULL; /* pour formater des chaines de characteres */
     
        /* création de la box verticale */
        pVBox = gtk_vbox_new(FALSE, 0);
        /* création de la box horizontale */
        pHBox = gtk_hbox_new(TRUE, 0);
        /* on détruit le label (ce qui permet - entre autre de l'enlever de son container) */
        gtk_widget_destroy(pLabel);
        /* et on le recrée */
        pLabel=gtk_label_new(NULL);
        (void)sprintf(format_sortie, "<span font_desc=\"25\"><b>00 : 00 : 00</b></span>");
        sUtf8 = g_locale_to_utf8(format_sortie, -1, NULL, NULL, NULL);
        gtk_label_set_markup(GTK_LABEL(pLabel), sUtf8);
        /* création du titre */
        pTitre=gtk_label_new(NULL);
        (void)sprintf(format_sortie, "<span font_desc=\"15\" background=\"#000000\" foreground=\"#FFFFFF\"><b>Testing..</b></span>");
        sUtf8 = g_locale_to_utf8(format_sortie, -1, NULL, NULL, NULL);
        gtk_label_set_markup(GTK_LABEL(pTitre), sUtf8);
        g_free(sUtf8);
        /* création du bouton reset */
        pButtonReset = gtk_button_new_with_label("Reset");
        /* création du bouton start */
        pButtonStart = gtk_button_new_with_label("Start");
        /* création du bouton stop */
        pButtonStop = gtk_button_new_with_label("Stop");
        /* création du timer */
        timer=g_timer_new();
        g_timer_stop(timer);
        /* AJout du titre dans la GtkVBox */
        gtk_box_pack_start(GTK_BOX(pVBox), pTitre, FALSE, TRUE, 10);
        /* Ajout des boutons reset, start dans la GtkHBox */
        gtk_box_pack_start(GTK_BOX(pHBox), pButtonStart, FALSE, TRUE, 0);
        gtk_box_pack_start(GTK_BOX(pHBox), pButtonStop, FALSE, TRUE, 0);
        gtk_box_pack_start(GTK_BOX(pHBox), pButtonReset, FALSE, TRUE, 0);
        /* ajout de la boite horizontale dans la boite verticale */
        gtk_box_pack_start(GTK_BOX(pVBox), pHBox, FALSE, TRUE, 0);
        /* ajout du label dans la GtkVBox */
        gtk_box_pack_start(GTK_BOX(pVBox), pLabel, TRUE, TRUE, 0);
        /* ajout de la GtkVBox à la fenetre */
        gtk_container_add(GTK_CONTAINER(pWindow), pVBox);
        /* modification de la taille de la fenêtre */
        gtk_window_resize(GTK_WINDOW(pWindow), 300, 100);
        /* deconnexion du signal capturé en étape 1 */
        g_signal_handler_disconnect(GTK_WINDOW(pWindow),handler_id);
        /* Connexion des autres signaux */
        g_signal_connect (G_OBJECT (pWindow), "key_press_event", G_CALLBACK (recup_key), NULL);
        g_signal_connect(G_OBJECT(pButtonStart),"pressed", G_CALLBACK(Press_Start), NULL);
        g_signal_connect(G_OBJECT(pButtonStop),"pressed", G_CALLBACK(Press_Stop), NULL);
        g_signal_connect(G_OBJECT(pButtonReset),"pressed", G_CALLBACK(Press_Reset), NULL);
        /* fonction appelée régulièrement .. */
        g_timeout_add ((guint)1, affichage,NULL);
        /* et on raffiche tout */
        gtk_widget_show_all(pWindow);
        return TRUE;
    }

    Pour le point 2:

    Bravo, et excellent l'idée de lancer le g_timeout_add() seulement quand on en a besoin (dans ce cas, après click sur "start"). Il y avait effectivement une erreur de conception ici, mais je n'avais pas saisi complètement le fait qu'on pouvait arréter l'appel à la callback en lui faisant retourner un FALSE quand c'était nécessaire. Très fort. Par ailleurs, en regardant un peu plus la documentation de GTK (je passe mes journées à ca en ce moment), je crois que j'ai trouvé comment me sortir de cette monopolisation trop fréquente de la CPU. Je dois faire encore quelques essais, mais je ne manquerai pas de donner le développement de ca, et la solution trouvée si elle fonctionne. Je précise accessoirement que je me fous du fait que la CPU soit sollicitée à plein. La machine est un multi-coeur et ne sera dédiée qu'à cette tâche. Ceci dit, je suis d'accord pour trouver un moyen plus élégant de faire ce que je souhaite faire, surtout si ca me fait mieux comprendre le fonctionnement et l'utilisation de GTK.

    Merci encore en tout cas pour l'aide (passée ou future). Vraiment très utile!

    Eric.

  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
    Juste pour la forme, tu as encore une fuite ligne 170. Tu masques la mémoire allouée ligne 165. Si je dis "juste pour la forme", c'est que ce bout de code n'est appelé qu'un fois, donc ça n'aura pas un effet dramatique, mais il te faut apprendre à les détecter à l'œil nu.

    Pour ce qui est de ton crash, tu peux me rappeler la version de GTK que tu utilises ? C'est GTK 2.x.y sous Windows il me semble, mais il me faudrait la valeur de x et y. Je sais qu'il y a des versions qui ont une fuite d'objets GDI. C'est une question à laquelle j'avais dû répondre il y a quelques temps sur un autre forum. Ah d'ailleurs, je viens de regarder le bug 671538, le patch n'a pas été intégré, donc aucune version de GTK 2 ne corrige actuellement le problème...

    Si tu veux en avoir le cœur net, lance ton programme avec le moniteur système configuré pour afficher le nombre d'objets GDI consommés par une application. Si tu le vois monter au fur et à mesure, il y a des chances que ça crashe arrivé à 10 000. Si c'est bien ça, c'est un bug spécifique au backend win32, et donc impossible à reproduire sous Linux. De toute façon, je t'avoue que ça ne me tentait pas trop de faire tourner un programme pendant 2H qui bouffe 100% d'un de mes cœurs .

    Il faudra ensuite relancer les développeurs pour voir si le correctif peut être intégré.

  9. #9
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    Citation Envoyé par liberforce Voir le message
    Juste pour la forme, tu as encore une fuite ligne 170. Tu masques la mémoire allouée ligne 165. Si je dis "juste pour la forme", c'est que ce bout de code n'est appelé qu'un fois, donc ça n'aura pas un effet dramatique, mais il te faut apprendre à les détecter à l'œil nu.

    Pour ce qui est de ton crash, tu peux me rappeler la version de GTK que tu utilises ? C'est GTK 2.x.y sous Windows il me semble, mais il me faudrait la valeur de x et y. Je sais qu'il y a des versions qui ont une fuite d'objets GDI. C'est une question à laquelle j'avais dû répondre il y a quelques temps sur un autre forum. Ah d'ailleurs, je viens de regarder le bug 671538, le patch n'a pas été intégré, donc aucune version de GTK 2 ne corrige actuellement le problème...

    Si tu veux en avoir le cœur net, lance ton programme avec le moniteur système configuré pour afficher le nombre d'objets GDI consommés par une application. Si tu le vois monter au fur et à mesure, il y a des chances que ça crashe arrivé à 10 000. Si c'est bien ça, c'est un bug spécifique au backend win32, et donc impossible à reproduire sous Linux. De toute façon, je t'avoue que ça ne me tentait pas trop de faire tourner un programme pendant 2H qui bouffe 100% d'un de mes cœurs .

    Il faudra ensuite relancer les développeurs pour voir si le correctif peut être intégré.
    Ok, alors, je reprends, et continues :

    1) Je suis sous GTK 2.24.10. C'est la dernière version stable d'après le site de GTK.

    2) Je suis/serais rassuré - si j'ose dire - que le problème vienne d'une fuite (connue) de la version de GTK que j'utilise, sans quoi, je serais vraiment à cours d'idée.

    3) Effectivement, en regardant mon code tourner dans le moniteur systeme, il grossit continuellement, trahissant probablement une fuite mémoire..

    4) si vraiment, le problème est lié à la version de GTK que j'utilise, que faire? J'ai pas trop envie de passer en version 3 (les infos que j'ai vu sur le web montrent que ce n'est pas trop stable et pas trop simple à poser, et accessoirement, ca implique une modification du code..). Comment on fait pour "relancer les développeurs pour voir si le correctif peut être intégré", par exemple?

    Je passe à présent au point 2 dans un de mes posts ci-dessus. A quoi sert mon application et pourquoi bouffer toute cette CPU? J'ai besoin d'une application qui écoute et capture tout ce qui vient soit du clavier, soit d'un port série (sur lequel est connecté un périphérique maison), et j'ai surtout besoin d’enregistrer la coordonnée temporelle de chaque événement capturé.

    En lisant - et relisant - la doc de GTK, j'ai fini par découvrir que la struct GdkEventKey possédait un élement time qui me donne effectivement la date de l'événement. J'ai fait des essais et ca marche très bien. Inutile d'écouter le clavier toutes les millisecondes. Je suis sauvé. Pour ce qui est de l'écoute du port série, je comprends qu'il vaille falloir que je jète effectivement un oeil aux GIOStream, mais je n'ai pas trop le temps pour l'instant. Je m'en occuperai plus tard.

    En tout cas, j'avance. Reste cette histoire de fuite mémoire (possible) qui n'est toujours pas résolue..

    Toute aide sur ce point reste la bienvenue, et encore merci pour votre temps.

    Eric.

  10. #10
    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
    Il ne faut pas confondre fuite mémoire et fuite d'objets GDI, les deux sont un peu différents. La fuite d'objets GDI est une sous-catégorie de fuite mémoire, l'interface GDI c'est un peu le pendant sous Windows de GDK.

    Pour diagnostiquer ton problème, il faut donc impérativement surveiller la consommation d'objets GDI pour la mettre en relation avec ton crash. Pas juste regarder globalement la consommation mémoire. Je t'ai indiqué comment faire dans mon post précédent. Si tu as besoin de plus d'explications, n'hésite pas.

    Pour ce qui est remonter les soucis au développeurs, une fois qu'on sera sûrs que c'est bien la cause de ton problème, je m'en occuperai, j'ai déjà commenté dans ce bug.

  11. #11
    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
    La fuite GDI est un des soucis, un autre est la fuite de pixmap du bug 685959. Elle a bien été corrigée, mais dans GTK 2.24.14. Tu n'es pas le premier à avoir ce soucis:
    http://stackoverflow.com/questions/1...50519#12950519

    Le problème c'est que cette version n'est pas disponible au téléchargement sur le site officiel de GTK, toujours par manque de mainteneur Windows... Il semble toutefois que la fuite a été introduite dans GTK 2.24.8, donc une version antérieure de GTK 2.24 pourrait faire l'affaire temporairement.

  12. #12
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    Citation Envoyé par liberforce Voir le message
    Il ne faut pas confondre fuite mémoire et fuite d'objets GDI, les deux sont un peu différents. La fuite d'objets GDI est une sous-catégorie de fuite mémoire, l'interface GDI c'est un peu le pendant sous Windows de GDK.

    Pour diagnostiquer ton problème, il faut donc impérativement surveiller la consommation d'objets GDI pour la mettre en relation avec ton crash. Pas juste regarder globalement la consommation mémoire. Je t'ai indiqué comment faire dans mon post précédent. Si tu as besoin de plus d'explications, n'hésite pas.

    Pour ce qui est remonter les soucis au développeurs, une fois qu'on sera sûrs que c'est bien la cause de ton problème, je m'en occuperai, j'ai déjà commenté dans ce bug.
    Bon, à force de chercher, j'ai fini par trouver sous windows 7 comment voir la consommation d'objets GDI. Le diagnostique est sans appel: Il n'y a aucune fuite de ce côté là. Le nombre d'objets GDI utilisés fluctue légèrement mais reste stable. En revanche, la quantité de mémoire utilisée, elle, croit constamment. Il y a bien une fuite quelque part.

    Je reste donc sans solution pour l'instant

    D'autres idées?

    Encore merci pour votre temps et votre aide,

    Eric.

  13. #13
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    Pour info - ou comme exemple - voici ci-dessous un code minimal qui régénère le même problème, au cas où ca serve dans la suite de la discussion.

    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
    #include <stdlib.h>
    #include <stdio.h>
    #include <gtk/gtk.h>
     
    guint x=0;
    char format_sortie[500];
     
    /* déclaration des widgets */
    GtkWidget *pWindow; /*fenetre principale */
    GtkWidget *pLabel; /* un label */
     
    /* fonction appelée à intervalle régulier */
    gboolean update(gpointer pData)
    {
        /* Mise a jour du label */
        gchar* sUtf8=NULL;
        x++;
        (void)sprintf(format_sortie, "<span font_desc=\"25\"><b>%d</b></span>",x);
        sUtf8 = g_locale_to_utf8(format_sortie, -1, NULL, NULL, NULL);
        gtk_label_set_markup(GTK_LABEL(pLabel), format_sortie);
        g_free(sUtf8);
        return TRUE;
    }
    int main(int argc, char **argv)
    {   
        /* Initialisation de GTK+ */
        gtk_init(&argc, &argv);
        /* création de la fenetre */
        pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        /* définition des paramètres de la fenetre */
        gtk_window_set_position(GTK_WINDOW(pWindow), GTK_WIN_POS_CENTER);
        gtk_window_set_default_size(GTK_WINDOW(pWindow), 300, 100);
        gtk_window_set_title(GTK_WINDOW(pWindow), "Memory leak");
     
        /* création du label */
        pLabel=gtk_label_new(NULL);
        (void)sprintf(format_sortie, "%d",x);
        gtk_label_set_text(GTK_LABEL(pLabel), format_sortie);
     
        /* ajout label à la fenetre */
        gtk_container_add(GTK_CONTAINER(pWindow), pLabel);
        /* Connexion des signaux */
        g_signal_connect(G_OBJECT(pWindow), "destroy", G_CALLBACK(gtk_main_quit), NULL);
        /* fonction appelée régulièrement  */
        g_timeout_add ((guint)1, update, NULL);
        /*affichage de la fenetre */
        gtk_widget_show_all(pWindow);
        /* Demarrage de la boucle evenementielle */
        gtk_main();
        return EXIT_SUCCESS;
    }
    Eric.

  14. #14
    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
    Je n'ai peut être pas été assez clair dans mon commentaire plus haut.

    Si le nombre d'objets GDI est stable, alors tu n'es pas affecté par une des fuites. En revanche, tu es à coup sûr affecté par une fuite mémoire due à un bug des versions Windows de GTK 2.24.8 à 2.24.14, puisque tu utilises GTK 2.24.10. La fuite survient chaque fois qu'un widget est rafraîchit. Et toi tu essaies de rafraîchir le label chaque milliseconde.

    Je ne peux pas vérifier que c'est ce qui provoque ton crash, je n'utilise que Linux, je n'ai pas de Windows à la maison. Si tu veux vérifier si ta fuite vient uniquement de là, il te suffit de commenter l'appel à gtk_label_set_markup dans la callback appelée par g_timeout_add. Ça ne devrait plus afficher tes changements, donc tu peux remplacer ça par un g_print dans une console si ça t'amuse, mais ça ne devrait plus non plus.

    Solution: comme la 2.24.14 n'est à ce jour pas dispo pour Windows en version pré-compilée (et que j'imagine que tu n'as pas envie de te prendre la tête à la compiler toi même), essaie une 2.24.0.
    http://ftp.gnome.org/pub/gnome/binar...n32/gtk+/2.24/

  15. #15
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    Citation Envoyé par liberforce Voir le message
    Je n'ai peut être pas été assez clair dans mon commentaire plus haut.

    Si le nombre d'objets GDI est stable, alors tu n'es pas affecté par une des fuites. En revanche, tu es à coup sûr affecté par une fuite mémoire due à un bug des versions Windows de GTK 2.24.8 à 2.24.14, puisque tu utilises GTK 2.24.10. La fuite survient chaque fois qu'un widget est rafraîchit. Et toi tu essaies de rafraîchir le label chaque milliseconde.

    Je ne peux pas vérifier que c'est ce qui provoque ton crash, je n'utilise que Linux, je n'ai pas de Windows à la maison. Si tu veux vérifier si ta fuite vient uniquement de là, il te suffit de commenter l'appel à gtk_label_set_markup dans la callback appelée par g_timeout_add. Ça ne devrait plus afficher tes changements, donc tu peux remplacer ça par un g_print dans une console si ça t'amuse, mais ça ne devrait plus non plus.

    Solution: comme la 2.24.14 n'est à ce jour pas dispo pour Windows en version pré-compilée (et que j'imagine que tu n'as pas envie de te prendre la tête à la compiler toi même), essaie une 2.24.0.
    http://ftp.gnome.org/pub/gnome/binar...n32/gtk+/2.24/
    Bonjour,

    Si, l'explication était très claire, et ma réponse montrait que j'avais bien compris, je pense.

    J'ai refais un test en commentant l'appel à gtk_label_set_markup dans la callback appelée par g_timeout_add. Effectivement, plus de trace de fuite.

    Il ne me reste plus qu'on poser, par exemple, la 2.24.0, en espérant que ca marche. En allant sur le site ftp correspondant, j'ai récupérer le fichier gtk+_2.24.0-1_win32.zip et l'ai extrait. Dois-je mettre les directories qui y sont présentes à la place de leur homologues en 2.24.10? Notamment, les includes restent-ils les mêmes, etc? Ceci m’étonne en fait, car - par exemple - la directory "bin" de la 2.24.10 possède 53 éléments, alors que celle de la 2.24.0 n'en possède que 4! (etc.).

    Merci pour cet (ultime?) aide!

    Eric.

  16. #16
    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
    Effectivement, je n'avais pas vu mais il n'y a pas de bundle pour GTK 2.24.0. Les bundle contiennent GTK + toutes ses dépendances. Donc je pense que tu dois avoir un bundle GTK 2.24.10 d'installé sur ta machine. Comme tu ne peux pas le remplacer par un bundle 2.24.0, alors il faut prendre la version binaire et dev de GTK 2.24.0, et la décompresser dans ton arborescence actuelle. Les includes GTK n'ont sans doute pas changé, mais dans le doute, il vaut mieux toujours tout mettre.

  17. #17
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    Citation Envoyé par liberforce Voir le message
    Effectivement, je n'avais pas vu mais il n'y a pas de bundle pour GTK 2.24.0. Les bundle contiennent GTK + toutes ses dépendances. Donc je pense que tu dois avoir un bundle GTK 2.24.10 d'installé sur ta machine. Comme tu ne peux pas le remplacer par un bundle 2.24.0, alors il faut prendre la version binaire et dev de GTK 2.24.0, et la décompresser dans ton arborescence actuelle. Les includes GTK n'ont sans doute pas changé, mais dans le doute, il vaut mieux toujours tout mettre.
    Effectivement, j'avais un bundle GTK 2.24.10.

    En clair, si je comprends bien, il faut que récupère gtk+_2.24.0-1_win32.zip et gtk+-dev_2.24.0-1_win32.zip, que je les décompresse, et que je je reverse le contenu de chaque directory dans celles du même nom de la version que j'ai déjà posée, au besoin en écrasant les fichiers qui y existaient. C'est bien ca?

    Eric.

  18. #18
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Octobre 2006
    Messages : 90
    Points : 92
    Points
    92
    Par défaut
    Bonjour,

    J'ai testé le code proposé au post #13 dans un Win7 virtualisé sous Debian.
    La version de GTK+ est la même que la votre, soit 2.24.10.
    Je l'ai laissé tourner environ un quart d'heure, les différentes plages mémoires restent stables et n'évoluent pas au fil du temps.
    L'utilisation processeur reste à 100% bien sur.

    Deux petites remarques :

    - dans la fonction update, pourquoi utiliser la conversion utf8 alors que vous ne vous en servez pas dans l'affectation au label ?

    - je n'ai pas fait le calcul, mais vous allouez une taille de 500 au buffer format_sortie.
    Vous utilisez sprintf, donc sans limitation de la copie ddans le buffer de destination. Comme je l'ai dit, je n'ai pas fait le calcul sur le nombre affiché au bout de deux heures, mais n'y aurait-il pas un bête dépassement de la mémoire allouée au buffer ?

    Car pour ma part, je ne vois rien d'autres qui poseraient problème dans votre code.

  19. #19
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    Citation Envoyé par _iri_ Voir le message
    Bonjour,

    J'ai testé le code proposé au post #13 dans un Win7 virtualisé sous Debian.
    La version de GTK+ est la même que la votre, soit 2.24.10.
    Je l'ai laissé tourner environ un quart d'heure, les différentes plages mémoires restent stables et n'évoluent pas au fil du temps.
    L'utilisation processeur reste à 100% bien sur.

    Deux petites remarques :

    - dans la fonction update, pourquoi utiliser la conversion utf8 alors que vous ne vous en servez pas dans l'affectation au label ?
    Oui, c'est une erreur effectivement. A la ligne 20, il faut lire effectivement:
    gtk_label_set_markup(GTK_LABEL(pLabel), sUtf8);

    Mais ca n'explique pas le problème.

    - je n'ai pas fait le calcul, mais vous allouez une taille de 500 au buffer format_sortie.
    Vous utilisez sprintf, donc sans limitation de la copie ddans le buffer de destination. Comme je l'ai dit, je n'ai pas fait le calcul sur le nombre affiché au bout de deux heures, mais n'y aurait-il pas un bête dépassement de la mémoire allouée au buffer ?

    Car pour ma part, je ne vois rien d'autres qui poseraient problème dans votre code.
    500 octets, c'est amplement suffisant pour y verser la chaine de caractères avec le sprintf. Je ne vois pas de problème de dépassement de mémoire ici.

    Comme je l'ai dit dans un post plus récent, la mise en commentaire de gtk_label_set_markup() arrete tous les problèmes de fuites mémoire que j'ai constatés. Le fait que vous ne trouviez rien de votre coté est peut-être due au fait que fassiez tourner ceci sous une émulation de windows 7 sous Debian?

    En tout cas, merci pour votre temps,

    Il ne me reste (apparemment) qu'à poser la 2.24.0..

    Eric.

  20. #20
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Octobre 2006
    Messages : 90
    Points : 92
    Points
    92
    Par défaut
    Pas de quoi.

    la fonction cairo_image_surface_get_data est utilisée de façon interne par GtkLabel pour un expose event.
    Code source https://git.gnome.org/browse/gtk+/tr...l.c?id=2.24.10 si cela peut avoir un intérêt pour vous à suivre le processus interne de GTK pour l'affichage.
    Bon courage !

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 6
    Dernier message: 12/05/2007, 00h31
  2. Plantage apres insertion de CD
    Par fallais dans le forum Périphériques
    Réponses: 11
    Dernier message: 16/02/2007, 18h32
  3. Portable qui se met en veille après 30 minutes
    Par Lanny dans le forum Windows XP
    Réponses: 2
    Dernier message: 07/12/2006, 22h57
  4. plantage après click sur le OK d'une messageBox
    Par cenedra dans le forum MFC
    Réponses: 7
    Dernier message: 31/07/2006, 08h43
  5. Arret de mon pc apres quelques minutes du check d'anti virus
    Par christophebmx dans le forum Sécurité
    Réponses: 4
    Dernier message: 01/07/2005, 14h50

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