gdb 调试(带断点):Gtk-WARNING **:无效的文本缓冲区迭代器

Bas*_*tch 5 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
Run Code Online (Sandbox Code Playgroud)

FWIW,有问题的程序是我正在开发的一些 GPLv3 自由软件(我问这个问题的目的相同,我在其中提供了更多上下文和解释)。它位于 github 上:commit fc8e0b247d8dac4(重现我的错误,构建它,运行它,在标有monimelt 命令的窗口中./monimelt准确输入)。p a y TAB

我已经尝试过(所有,在同一个gdb会话中):

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

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

  • 在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);
    
    Run Code Online (Sandbox Code Playgroud)

    别帮忙...

但尚未到达这些断点,并且该Gtk-WARNING **: Invalid text buffer iterator消息仍然出现。

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

我是如何发现我的错误的......

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

我对发现 bug 的方式并不满意。我必须获取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;
    }
Run Code Online (Sandbox Code Playgroud)

我所做的唯一更改(关于原始 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
Run Code Online (Sandbox Code Playgroud)

我认为这是一个虚假警告,因为我运行的桌面是 Mate,而不是 Gnome。我的代码正在调用gtk_application_new&g_application_runactivate在我的mom_gtkapp.


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