这是赤裸裸的
save_as()
gint save_as(GtkWidget *parent, struct buffers B)
{
GtkWidget *file_chooser = gtk_file_chooser_dialog_new("Save As", GTK_WINDOW(parent), GTK_FILE_CHOOSER_ACTION_SAVE, "Cancel", GTK_RESPONSE_CANCEL, "Save", GTK_RESPONSE_OK, NULL);
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(file_chooser), "Untitled");
gint response = gtk_dialog_run(GTK_DIALOG(file_chooser));
switch(response)
{
case GTK_RESPONSE_OK:
GFile *file = g_file_new_for_path(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_chooser)));
GtkTextIter *start;
gtk_text_buffer_get_start(B.buffer0, &start);
GtkTextIter *end;
gtk_text_buffer_get_end(B.buffer0, &end);
// program abnormally terminates on the following line
gchar *contents = gtk_text_buffer_get_text(B.buffer0, &start, &end, FALSE);
g_file_replace_contents(file, contents, strlen(contents), NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL, NULL);
g_free(contents);
gtk_widget_destroy(file_chooser);
return GTK_RESPONSE_OK;
break;
case GTK_RESPONSE_CANCEL:
gtk_widget_destroy(file_chooser);
return GTK_RESPONSE_CANCEL;
}
// user pressed X
gtk_widget_destroy(file_chooser);
return GTK_RESPONSE_CANCEL;
}
这几乎是我们诊断和解决问题所需要的全部。
这是我尝试点击时得到的完整信息
保存
(test:4478): Gtk-WARNING **: 11:56:20.184: Invalid text buffer iterator: either the iterator is uninitialized, or the characters/pixbufs/widgets in the buffer have been modified since the iterator was created.
You must use marks, character numbers, or line numbers to preserve a position across buffer modifications.
You can apply tags and insert marks without invalidating your iterators, but any mutation that affects 'indexable' buffer contents (contents that can be referred to by character offset) will invalidate all outstanding iterators
(test:4478): Gtk-CRITICAL **: 11:56:20.184: gtk_text_buffer_get_text: assertion 'gtk_text_iter_get_buffer (start) == buffer' failed
Segmentation fault (core dumped)
出于某种原因,迭代器
start
和
end
不属于
B.buffer0
GTK+3 documentation
,我也跟着回答
this question
作为向导。
为什么会发生这种情况,如何解决?
gtk_text_buffer_get_start_iter(B.buffer0, &start);
到
gtk_text_buffer_get_start_iter(B.buffer0, start);
gtk_text_buffer_get_start_iter(B.buffer0, &end);
到
gtk_text_buffer_get_start_iter(B.buffer0, end);
gchar *contents = gtk_text_buffer_get_text(B.buffer0, &start, &end, FALSE);
gchar *contents = gtk_text_buffer_get_text(B.buffer0, start, end, FALSE);
唯一的错误是:
Segmentation fault (core dumped)
这也应该是根据
documentation
.
另外,我试着替换
contents = gtk_text_buffer_get_text(B.buffer0, start, end, FALSE);
具有
contents = gtk_text_iter_get_text(start, end);
我还注意到,在应用这些更改之后,在编译过程中会收到两个警告:
src/save.c:96:5: warning: âstartâ may be used uninitialized in this function [-Wmaybe-uninitialized]
gtk_text_buffer_get_start_iter(B.buffer0, start);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/save.c:98:5: warning: âendâ may be used uninitialized in this function [-Wmaybe-uninitialized]
gtk_text_buffer_get_end_iter(B.buffer0, end);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
这显然意味着
gtk_text_buffer_get_start/end_iter()
开始
结束
具有
,但为什么?上面说
结束
结构缓冲区的定义在一个名为
buffer.h
. 这里是(不是整个文件,只是结构定义):
struct buffers
{
GtkTextBuffer *buffer0;
GtkTextBuffer *buffer1;
GtkTextBuffer *buffer2;
};
我使用的实例是:
struct buffers Buffer;
包含在每个使用
Buffer
. 当然,为了同样的目的(全球性),它是被宣布的
extern struct buffers Buffer;
在与定义它的源文件关联的头文件中。
这个缓冲区被传递给一个函数
另存为()
gint response = save_as(main_window, Buffer);
如果您想知道为什么我不使用全局变量而不是将其作为参数传递,那是因为我可以传递任何类型的变量
struct buffers
到
save_file()
结构缓冲区
变量。
GtkTextIter *start = NULL;
GtkTextIter *end = NULL;
文件->另存为
然后
,程序退出,我收到消息:
(test:4081): Gtk-CRITICAL **: 19:48:29.843: gtk_text_buffer_get_start_iter: assertion 'iter != NULL' failed
(test:4081): Gtk-CRITICAL **: 19:48:29.844: gtk_text_buffer_get_end_iter: assertion 'iter != NULL' failed
(test:4081): Gtk-CRITICAL **: 19:48:29.844: gtk_text_buffer_get_text: assertion 'start != NULL' failed
开始
和
结束
迭代器是
NULL
开始
和
结束
分别指向文件开头和结尾的迭代器?因此,为什么在这之前设置什么迭代器很重要呢?