迭代器不属于其分配的文本缓冲区

2023-12-24

这是一个简单的骨头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;
}

这几乎就是我们诊断和解决问题所需的全部内容。

这是我尝试单击时收到的完整消息文件 -> 另存为...然后继续Save:

(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 and end不属于B.buffer0。除了GTK+3 文档 https://developer.gnome.org/gtk3/stable/,我也关注了答案这个问题 https://stackoverflow.com/questions/11088338/how-to-save-content-of-gtktextbuffer-to-a-file作为指导。

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


I also tried changing the following lines:

gtk_text_buffer_get_start_iter(B.buffer0, &start); to gtk_text_buffer_get_start_iter(B.buffer0, start);

gtk_text_buffer_get_start_iter(B.buffer0, &end); to gtk_text_buffer_get_start_iter(B.buffer0, end);

gchar *contents = gtk_text_buffer_get_text(B.buffer0, &start, &end, FALSE); to gchar *contents = gtk_text_buffer_get_text(B.buffer0, start, end, FALSE);

我得到的唯一错误是:

Segmentation fault (core dumped)

这也应该是根据以下内容发送参数的正确方法文档 https://developer.gnome.org/gtk3/stable/GtkTextBuffer.html.

另外,我尝试更换contents = gtk_text_buffer_get_text(B.buffer0, start, end, FALSE); with 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()关联失败start and end with B.buffer0, 但为什么?它说start and end未初始化就传递了,但这不是正常的吗,因为我现在正在初始化它们?或者我应该在那之前做点什么?


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 to a save_file()并让它完成工作,而不是为每个功能提供另一个功能struct buffers多变的。


I tried initializing iterators upon their definition:
GtkTextIter *start = NULL;
GtkTextIter *end = NULL;

一切都会编译,没有任何警告。不幸的是,这并不能解决问题。点击后文件 -> 另存为进而Save,程序退出,我收到消息:

(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

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


终于解决了。看起来像那样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;
}

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

Wrong

GtkTextIter *start;
GtkTextIter *end;

Right

GtkTextIter start;
GtkTextIter end;

大多数 GTK 类型都希望您将它们设为指针,但这个是一个例外。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

迭代器不属于其分配的文本缓冲区 的相关文章

  • 编译时运算符

    有人可以列出 C 中可用的所有编译时运算符吗 C 中有两个运算符 无论操作数如何 它们的结果始终可以在编译时确定 它们是sizeof 1 and 2 当然 其他运算符的许多特殊用途可以在编译时解决 例如标准中列出的那些整数常量表达式 1 与
  • 以文化中立的方式将字符串拆分为单词

    我提出了下面的方法 旨在将可变长度的文本拆分为单词数组 以进行进一步的全文索引处理 删除停止词 然后进行词干分析 结果似乎不错 但我想听听关于这种实现对于不同语言的文本的可靠性的意见 您会建议使用正则表达式来代替吗 请注意 我选择不使用 S
  • 动态加载程序集的应用程序配置

    我正在尝试将模块动态加载到我的应用程序中 但我想为每个模块指定单独的 app config 文件 假设我的主应用程序有以下 app config 设置
  • 用于检查类是否具有运算符/成员的 C++ 类型特征[重复]

    这个问题在这里已经有答案了 可能的重复 是否可以编写一个 C 模板来检查函数是否存在 https stackoverflow com questions 257288 is it possible to write a c template
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • 为什么当实例化新的游戏对象时,它没有向它们添加标签? [复制]

    这个问题在这里已经有答案了 using System Collections using System Collections Generic using UnityEngine public class Test MonoBehaviou
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 使用 WebClient 时出现 System.Net.WebException:无法创建 SSL/TLS 安全通道

    当我执行以下代码时 System Net ServicePointManager ServerCertificateValidationCallback sender certificate chain errors gt return t
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • WCF 中 SOAP 消息的数字签名

    我在 4 0 中有一个 WCF 服务 我需要向 SOAP 响应添加数字签名 我不太确定实际上应该如何完成 我相信响应应该类似于下面的链接中显示的内容 https spaces internet2 edu display ISWG Signe
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低

随机推荐