c - gtk_label_set_text() 段错误

标签 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:断言“PANGO_IS_LAYOUT(布局)”失败 (1:18144):Pango-CRITICAL **:pango_layout_get_iter:断言“PANGO_IS_LAYOUT(布局)”失败
然后是段错误。

我通过dmesg命令查看了它的信息。我明白了。
[ 703.437988] 1[6358]: 段错误 10 ip 00007f9b07ac3f91 sp 00007ffe3bd53790 libpango-1.0.so.0.3800.1[7f9b07aa0000+48000] 中的错误 4

这个错误我该怎么办?

最佳答案

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

你最好的选择是避免线程:设计你的代码,使主循环永远不会被长时间阻塞。通常当我看到线程问题时,线程的使用是不必要的,整个困惑可以通过更简洁的设计来避免。

如果无法以更好的方式设计代码,那么您需要使用例如g_main_context_invoke()在您的其他线程中调用主线程中的函数:该函数然后可以安全地修改 Gtk+ 小部件状态。小心不要在线程之间共享指针的生命周期时出错。

关于c - gtk_label_set_text() 段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33470708/

相关文章:

比较C中的unsigned char数组

c++ - 如何使用 C/C++ 检查文件系统是否已安装

linux - 对 3 列进行排序并求平均值

linux - 我应该在 MapReduce 模式下启动 Pig 之前启动 Hadoop 集群吗?

c - 如何从选定的 gtk_combo_box 项目中获取字符串?

c - 在 C 中,如何删除 char 数组中相同且连续的行?

C - 从不同的函数访问结构变量

gtk - 在对话窗口中使用 Glade,如何为按钮添加响应

我可以使用线程来更改 GTK 镜像吗?

c - 为什么 C 没有 snwprintf 函数?