gtk_label_set_text()分段错误

时间:2015-11-02 04:20:50

标签: c linux gtk

这是我的代码。

#include <gtk/gtk.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>

#define MAX_LENGTH 8
#define WIDGET_NUM 3

typedef struct Widget
{
    GtkWidget *window;
    GtkWidget *button[WIDGET_NUM];
    GtkWidget *entry[WIDGET_NUM];
    GtkWidget *label[WIDGET_NUM];
    GtkWidget *grid;
    pthread_t pid[WIDGET_NUM];
    int button_num;
}Widget;

void num_2_time(int num, char *buf)
{
    int h = num / 3600;
    int m = num % 3600 / 60;
    int s = num % 60;

    sprintf(buf, "%d:%d:%d", h, m, s);
}

void *wait_4_waking(void *arg)
{
    Widget *window = (Widget*)arg;
    int input_num, window_num = window->button_num;
    const char *text;
    char buf[MAX_LENGTH * 2];

    text = gtk_entry_get_text(GTK_ENTRY(window->entry[window_num]));
    input_num = atoi(text);
    gtk_entry_set_text(GTK_ENTRY(window->entry[window_num]), "");

    while (input_num >= 0)
    {
        num_2_time(input_num, buf);
        //Segmentation fault
        gtk_label_set_text(GTK_LABEL(window->label[window_num]), buf);
        sleep(1);
        input_num--;
    }

    return NULL;
}

void button_clicked_0(GtkWidget *widget, gpointer data)
{
    Widget *window = (Widget*)data;
    window->button_num = 0;

    printf("%u\n", window->pid[0]);
    if (window->pid[0] > 0)
    {
        pthread_cancel(window->pid[0]);
    }
    pthread_create(window->pid, NULL, wait_4_waking, data);
}
void button_clicked_1(GtkWidget *widget, gpointer data)
{
    Widget *window = (Widget*)data;
    window->button_num = 1;

    if (window->pid[1] > 0)
    {
        pthread_cancel(window->pid[1]);
    }
    pthread_create(window->pid+1, NULL, wait_4_waking, data);
}
void button_clicked_2(GtkWidget *widget, gpointer data)
{
    Widget *window = (Widget*)data;
    window->button_num = 2;

    if (window->pid[2] > 0)
    {
        pthread_cancel(window->pid[2]);
    }
    pthread_create(window->pid+2, NULL, wait_4_waking, data);
}


int main (int argc, char **argv)
{
    Widget window;
    int i;
    void (*button_clicked[WIDGET_NUM])(GtkWidget*, gpointer) = {
        button_clicked_0, button_clicked_1, button_clicked_2
    };

    gtk_init(&argc, &argv);

    window.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title (GTK_WINDOW (window.window), "Window");
    gtk_window_set_default_size (GTK_WINDOW (window.window), 400, 200);

    window.grid = gtk_grid_new();
    for (i = 0; i < WIDGET_NUM; i++)
    {
        window.entry[i] = gtk_entry_new();
        window.label[i] = gtk_label_new("0:0:0");
        window.button[i] = gtk_button_new_with_label("Go!");
        window.pid[i] = 0;
        gtk_entry_set_max_length(GTK_ENTRY(window.entry[i]), MAX_LENGTH);
        gtk_grid_attach(GTK_GRID(window.grid), window.entry[i], 0, i, 1, 1);
        gtk_grid_attach(GTK_GRID(window.grid), window.button[i], 1, i, 1, 1);
        gtk_grid_attach(GTK_GRID(window.grid), window.label[i], 2, i, 1, 1);
    }
    gtk_container_add (GTK_CONTAINER (window.window), window.grid);

    for (i = 0; i < WIDGET_NUM; i++)
    {
        g_signal_connect (window.button[i], "clicked", G_CALLBACK (button_clicked[i]), (gpointer)&window);
    }

    g_signal_connect (window.window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

    gtk_widget_show_all (window.window);
    gtk_main();

    return 0;
}

构建命令:

  

gcc -o 1 test2.c`pkg-config --libs --cflags gtk + -3.0` -pthread -g


当我点击按钮时发生了这个错误,但它并没有一直发生。
在发生之前,我会在下面得到一个信息。
(1:18144): Pango-CRITICAL **: pango_layout_get_pixel_extents: assertion 'PANGO_IS_LAYOUT (layout)' failed (1:18144): Pango-CRITICAL **: pango_layout_get_iter: assertion 'PANGO_IS_LAYOUT (layout)' failed
然后分段错误。

我通过dmesg命令检查了它的信息。而我得到了这个。
[ 703.437988] 1[6358]: segfault at 10 ip 00007f9b07ac3f91 sp 00007ffe3bd53790 error 4 in libpango-1.0.so.0.3800.1[7f9b07aa0000+48000]

如何处理此错误?

1 个答案:

答案 0 :(得分:1)

您正在从另一个线程调用Gtk +小部件功能。 Gtk +不是线程安全的,所以不要这样做。

您最好的选择是避免线程:设计代码,以便主循环永远不会被阻塞。通常当我看到线程问题时,线程的使用是不必要的,并且通过更清洁的设计可以避免整个混乱。

如果代码无法以更好的方式设计,那么您需要使用例如{/ 3}}在你的另一个线程中调用主线程中的一个函数:该函数可以安全地修改Gtk + widget状态。注意不要在线程之间共享的指针的生命周期中出错。