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.