c - gdb调试(带断点): Gtk-WARNING **: Invalid text buffer iterator

标签 c linux debugging gdb gtk3

我如何使用 gdb 调试(并到达某个断点)我的错误程序(使用 GTK3)显示:

(monimelt:161): Gtk-WARNING **: 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

FWIW,有问题的程序是我正在开发的一些 GPLv3 免费软件(我在 this question 中询问过,我在其中提供了更多上下文和解释)。它在 github 上:commit fc8e0b247d8dac4 (要重现我的错误,构建它,以 ./monimelt 运行它,准确键入 p a y < kbd>TAB 在标有 monimelt 命令 的窗口中。

我已经试过了(全部都在同一个 gdb session 中):

  • 在我的 main 中很早就调用了 g_log_set_default_handler使用我自己的 mom_g_log_handler 日志处理程序函数(如建议的 here )并在那里放置一个 gdb 断点

  • g_warning 上放置一个 gdb 断点(不起作用,因为它可能是一个宏)

  • g_log_default_handler 上设置 gdb 断点

  • 同时调用(在提交 fb374425c69f2ddbd... 中)

    g_log_set_handler ("Gtk", G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL
                       | G_LOG_LEVEL_ERROR | G_LOG_LEVEL_WARNING
                       | G_LOG_FLAG_RECURSION, mom_g_log_handler, NULL);
    

    不要帮忙...

但是那些断点没有到达,Gtk-WARNING **: Invalid text buffer iterator 消息仍然出现。

也许 GTK 正在创建一些 pthreads,或者它正在注册自己的日志处理程序...

我是怎么发现我的错误的....

我终于找到了我的错误(在提交 82bb111402fdd97... 中更正)。在 gtk_text_buffer_insert 之后(错误地)发生了两次对 gtk_text_iter_get_offset 的调用。

但是我对发现错误的方式不满意。我不得不取 gtk+-3.21.6.tar.xz我修补了它的 gtk/gtktextiter.c 以在第 180 行附近编写以下代码:

extern void basile_gtk_text_iter_warning (void);
void basile_gtk_text_iter_warning (void)
{
  usleep (1000);
}

/* This function ensures that the segment-dependent information is
   truly computed lazily; often we don't need to do the full make_real
   work. This ensures the btree and line are valid, but doesn't
   update the segments. */
static GtkTextRealIter*
gtk_text_iter_make_surreal (const GtkTextIter *_iter)
{
  GtkTextRealIter *iter = (GtkTextRealIter*)_iter;

  if (iter->chars_changed_stamp !=
      _gtk_text_btree_get_chars_changed_stamp (iter->tree))
    {
      g_warning ("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.\nYou must use marks, character numbers, "
                 "or line numbers to preserve a position across buffer "
                 "modifications.\nYou can apply tags and insert marks "
                 "without invalidating your iterators,\n"
                 "but any mutation that affects 'indexable' buffer contents "
                 "(contents that can be referred to by character offset)\n"
                 "will invalidate all outstanding iterators");
      basile_gtk_text_iter_warning ();
      return NULL;
    }

我所做的唯一更改(w.r.t. pristine GTK3.21.26)是对 basile_gtk_text_iter_warning 的定义和调用,我使用 gdb 在其中放置了一个断点。

能够做这样卑鄙的把戏是我尽可能只使用免费软件的原因之一,但不得不做这样的把戏实在是一种耻辱,必须有更好的方法。

所以我的问题仍然存在,我怎么能放置这样一个断点而不重新编译 GTK3?或者更一般地说,我如何使用 GDB 来捕获此类错误(当然无需重新编译 GTK3)。

顺便说一句,使用简单的 --g-fatal-warnings 选项并不是真正的解决方案,因为我也得到了

(monimelt:21949): Gtk-WARNING **: Failed to get the GNOME session proxy: 
The name org.gnome.SessionManager is not owned

我认为这是虚假警告,因为我运行的桌面是 Mate,而不是 Gnome。我的代码正在调用 gtk_application_new & g_application_run 并且在我的 mom_gtkapp 上有一个 activate 信号。


附言。在 Linux/Debian/Sid/x86-64 上,GTK3 是 3.21.5,使用 GCC6 和 -g3 -Og 标志编译...

最佳答案

您可以通过在 g_logv 上放置断点来中断 g_warning(以及任何其他日志级别消息)。

我在这里找到了这个信息,仅供引用:http://wiki.inkscape.org/wiki/index.php/Debugging_Inkscape

关于c - gdb调试(带断点): Gtk-WARNING **: Invalid text buffer iterator,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39509231/

相关文章:

c - C 中的无限循环 fscanf

java - "\n","\t"如何分别加新行和制表符?

Java/Linux : sound output on wrong card

linux - Linux内核源代码位置

javascript - 为什么这个函数会提示 URL 但没有提示字符串段?

c# - 调试 WPF 时遇到问题

c - 按字母顺序对链接列表进行排序

c++ - 如何识别C或C++

c - (((long)*(ptr)) << 1) >> 1;

python - 如何使用 Pycharm 调试 python 脚本?