迭代器不属于其指定的文本缓冲区

问题描述 投票:1回答:1

这是一个简单的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)

由于某种原因,似乎迭代器startend不属于B.buffer0。除了GTK+3 documentation,我也按照this question的答案作为指导。

为什么会发生这种情况以及如何解决这个问题?


I also tried changing the following lines:

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()无法将startendB.buffer0联系起来,但为什么呢?它说startend是未经初始化的,但是因为我现在正在初始化它们并不正常吗?或者我应该在那之前做点什么?


Definition of struct buffer is in a file called buffer.h. Here it is (not the whole file, just the struct definition):
struct buffers
{
    GtkTextBuffer *buffer0;
    GtkTextBuffer *buffer1;
    GtkTextBuffer *buffer2;
};

我使用的实例是:

struct buffers Buffer;

这是一个全局变量,因此buffer.h包含在使用Buffer的每个文件中。并且出于同样的目的(全局性),当然它在与定义它的源文件相关联的头文件中声明为extern struct buffers Buffer;

这个缓冲区传递给函数save_as(),如下所示:

gint response = save_as(main_window, Buffer);

如果您想知道我为什么不使用全局变量而不是将其作为参数传递,那是因为我可以将struct buffers类型的任何变量传递给save_file()并让它完成工作,而不是使用其他函数对于每个struct buffers变量。


I tried initializing iterators upon their definition:
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

至少在前两种情况下,为什么我的startend迭代器至少是NULL?这两个函数不应该分别将startend迭代器设置为文件的开头和结尾吗?因此,为什么在此之前设置迭代器很重要?

c gtk gtk3
1个回答
0
投票

终于解决了。看起来GtkTextIter与大多数GTK类型略有不同。

这是应该怎么做:

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;
}

如您所见,此代码与我的问题中的代码的唯一区别在于以下两行:

错误

GtkTextIter *start;
GtkTextIter *end;

GtkTextIter start;
GtkTextIter end;

大多数GTK类型都希望你使它们成为指针,但这个是一个例外。

© www.soinside.com 2019 - 2024. All rights reserved.