使用 GtkTextBuffer 意外中止
Unexpected abort using GtkTextBuffer
我正在开发一个基于 Gtk 的应用程序,我需要每隔 X 秒更新一个 GtkTextBuffer,方法是连接已经存在的文本。显然它成功了,但有时 "randomly" 应用程序中止,我认为这是由于这个因素造成的,因为它以前没有发生过。它有时会在 second/third 更新时中止(每次更新只添加一个新行),有时它根本不会中止。我将 TextBuffer 更新功能基于简单的聊天应用程序行为,但我不知道自己做错了什么。更新函数为:
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的相关代码是:
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" 回调中调用的。
感谢您的帮助
该代码没有意义。您正在连接成一个没有 space 的字符串来容纳更多文本,这是等待发生的未定义行为!您发布的答案也没有意义,创建这样的文本副本毫无意义。这可能会有所帮助,因为它更多地使用了堆,所以也许你会更幸运。连接成 previous_text
.
的行为仍未定义
如果您想追加更多文字,则无需重新设置整个文字内容。只需首先使用 gtk_text_buffer_insert()
to insert new text at the end. Use gtk_text_buffer_get_iter_at_offset()
来获取缓冲区内容末尾的迭代器。
UPDATE 哦,还有,你绝对不能 从多个线程调用 GTK+。它不是一个线程安全的库,所以不要那样做。有点不清楚你是否这样做,但听起来确实是这样。
我正在开发一个基于 Gtk 的应用程序,我需要每隔 X 秒更新一个 GtkTextBuffer,方法是连接已经存在的文本。显然它成功了,但有时 "randomly" 应用程序中止,我认为这是由于这个因素造成的,因为它以前没有发生过。它有时会在 second/third 更新时中止(每次更新只添加一个新行),有时它根本不会中止。我将 TextBuffer 更新功能基于简单的聊天应用程序行为,但我不知道自己做错了什么。更新函数为:
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的相关代码是:
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" 回调中调用的。
感谢您的帮助
该代码没有意义。您正在连接成一个没有 space 的字符串来容纳更多文本,这是等待发生的未定义行为!您发布的答案也没有意义,创建这样的文本副本毫无意义。这可能会有所帮助,因为它更多地使用了堆,所以也许你会更幸运。连接成 previous_text
.
如果您想追加更多文字,则无需重新设置整个文字内容。只需首先使用 gtk_text_buffer_insert()
to insert new text at the end. Use gtk_text_buffer_get_iter_at_offset()
来获取缓冲区内容末尾的迭代器。
UPDATE 哦,还有,你绝对不能 从多个线程调用 GTK+。它不是一个线程安全的库,所以不要那样做。有点不清楚你是否这样做,但听起来确实是这样。