2017-01-09 2 views
0

Я разрабатываю приложение на основе Gtk, где мне нужно обновлять каждые X секунд GtkTextBuffer, объединяя текст, который уже существует. По-видимому, это удается, но иногда «случайным образом» приложение прерывается, и я предполагаю, что это связано с этим элементом, чего раньше не было. Иногда он прерывается, когда есть второе/третье обновление (каждое обновление добавляет только одну новую строку), и иногда оно вообще не прерывается. Я основал функцию обновления TextBuffer для простого поведения приложений чата, но я не знаю, что я делаю неправильно. Функция обновления:Неожиданное прерывание с использованием GtkTextBuffer

void updateTextWindow(char *new_msg){ 
    g_print("Msg rcv: %s\n", new_msg); 
    GtkTextIter start, end; 
    GtkTextBuffer *buffer = gtk_text_view_get_buffer (global_text_window); 
    //global_text_window is a global gtkwidget where TextBuffer is embedded 
    gchar *previous_text; 

    gtk_text_buffer_get_bounds (buffer, &start, &end); 
    previous_text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE); 

    strcat(previous_text, "\n"); 
    strcat(previous_text, new_msg); 

    gtk_text_buffer_set_text(buffer, previous_text, -1); 

    g_free(previous_text); 
} 

Кроме того соответствующий код в основной функции, где все GtkWidgets объявлены и initializated является:

void create_ui (CustomData *data) { 

    [...] 

    GtkWidget *secondary_box; /* for text entry & buffer */ 
    GtkScrolledWindow *scrolling_box; 
    GtkWidget *text_window; 
    GtkTextBuffer *buffer; 
    GtkWidget *text_entry; 

    secondary_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 1); 
    gtk_widget_set_size_request(secondary_box, 600, -1); 
    scrolling_box = gtk_scrolled_window_new(NULL, NULL); 
    gtk_scrolled_window_set_policy(scrolling_box, GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); 
    text_entry = gtk_entry_new(); 
    global_text_entry = text_entry; 
    gtk_entry_set_max_length(text_entry, 25); 

    text_window = gtk_text_view_new(); 
    buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_window)); 
    gtk_text_buffer_set_text(buffer, "\n", -1); 
    gtk_text_view_set_editable(text_window, FALSE); 
    global_text_window = text_window; 
    gtk_scrolled_window_add_with_viewport(scrolling_box, text_window); 

    gtk_box_pack_end(GTK_CONTAINER(secondary_box), text_entry, FALSE, FALSE, 0); 
    g_signal_connect(G_OBJECT(text_entry), "activate", G_CALLBACK(text_entry_cb), &data); 
    gtk_box_pack_end(GTK_CONTAINER(secondary_box), scrolling_box, TRUE, TRUE, 0); 

    [...] 
} 

функция обновления вызывается из другого потока, а не от «Activate "обратный вызов для виджета ввода текста.

Спасибо за вашу помощь

ответ

2

Этот код не имеет смысла. Вы объединяетесь в строку, в которой нет места для хранения большего текста, это неопределенное поведение, ожидающее своего появления! Ваш ответ также не имеет смысла, нет смысла создавать копию такого текста. Это может помочь только потому, что он использует кучу немного больше, так что, возможно, вам повезет. Все еще неопределенное поведение для конкатенации в previous_text.

Если вы хотите добавить больше текста, нет необходимости повторно устанавливать содержимое всего текста. Просто используйте gtk_text_buffer_insert(), чтобы вставить новый текст в конец. Сначала используйте gtk_text_buffer_get_iter_at_offset(), чтобы получить итератор для конца содержимого буфера.

UPDATE О, а также, вы абсолютно не может вызов GTK + из нескольких потоков. Это не потокобезопасная библиотека, поэтому не делайте этого. Это немного неясно, если вы это сделаете, но это точно похоже на это.

+2

Вы забыли поговорить о другой части причины сбоя кода: GTK + не является потокобезопасным; все настройки GtkTextBuffer должны быть сделаны в основном потоке, используя 'gdk_threads_add_idle()' для планирования действий основного потока. – andlabs

+0

@andlabs Спасибо, исправлено. – unwind

Смежные вопросы