2

大多数时候我的 GLib 程序运行良好。但是,当日志喜欢

**(进程:pid):消息(递归):blah lah blah

出现,程序将中止。

GLib 手册说 G_LOG_FLAG_RECURSION 默认被认为是致命的。

但我就是不明白“递归消息”是什么意思?什么时候会出现递归消息?

谢谢

4

2 回答 2

3

浏览 glib/gmessages.c 给我一个非常强烈的印象,G_LOG_FLAG_RECURSION如果g_logv()需要自己记录错误的话。

考虑内存不足;当内存分配尝试失败时,程序将尝试记录内存分配失败,并可能退出。当日志记录例程尝试分配内存来记录消息时,它可能会失败。因此,如果是递归日志调用,日志记录例程会跟踪它们被调用的“深度”,并切换内存分配策略(它们在堆栈上而不是在堆上分配)。

每当日志记录例程收到错误消息并想要记录错误时,就会发生一些非常糟糕的事情,因此尝试使用另一种机制进行日志记录然后退出是有意义的。

所以你可能只是看到了真正问题的一个遥远的症状。您可以使用ltrace(1)来尝试发现问题,或者您可以启用核心转储 ( ) 并尝试使用 gdb 的命令ulimit -c unlimited查找导致程序崩溃的调用链。bt

于 2010-09-01T10:37:23.563 回答
3

请注意,如果您正在注册自定义处理程序(使用g_log_set_handler)并且该处理程序(或其被调用者之一)尝试通过调用 g_* 例程来记录错误,则也可能会发生对 g_* 日志记录例程的递归调用。

另请注意,glib 决定任何递归也应该是致命的(即使不是无限的只有一层深度)。这对于 sarnold 对内部故障递归的回答中描述的情况当然是有意义的,但在自定义处理程序重复出现的情况下尝试解决问题时可能并不明显。因此,glib 早在第一次递归调用 g_* 时就检测到递归;它甚至没有检查您的自定义处理程序是否已附加。因此,您将永远不会看到对处理程序的递归调用。所有这一切意味着在处理程序的主体(和类似的事情)中小心地取消注册处理程序等努力是徒劳的。

您必须绝对确保自定义处理程序的调用堆栈中的任何内容都不会调用 g_* 例程(如果您处理对外部代码的调用并且确实使尝试将日志消息传递到远程目的地等事情变得复杂,这可能会变得很棘手或者其他的东西)。

于 2010-10-22T00:25:18.357 回答