Logging 为什么GLib会在递归日志下中止?
大多数时候,我的能说会道的程序运行得很好。但是,当日志 **(进程:pid):消息(递归):废话 出现时,程序将中止 GLib手册说,默认情况下,G_LOG_FLAG_递归被认为是致命的 但我就是不明白“递归消息”是什么意思?什么时候会出现递归消息Logging 为什么GLib会在递归日志下中止?,logging,glib,Logging,Glib,大多数时候,我的能说会道的程序运行得很好。但是,当日志 **(进程:pid):消息(递归):废话 出现时,程序将中止 GLib手册说,默认情况下,G_LOG_FLAG_递归被认为是致命的 但我就是不明白“递归消息”是什么意思?什么时候会出现递归消息 谢谢浏览glib/gmessages.c给我的印象非常深刻,如果G\u logv()需要记录错误本身,则设置了G\u LOG\u FLAG\u递归 考虑内存不足;当内存分配尝试失败时,程序将尝试记录内存分配失败,并可能退出。当日志例程试图分配内存来记
谢谢浏览glib/gmessages.c给我的印象非常深刻,如果
G\u logv()
需要记录错误本身,则设置了G\u LOG\u FLAG\u递归
考虑内存不足;当内存分配尝试失败时,程序将尝试记录内存分配失败,并可能退出。当日志例程试图分配内存来记录消息时,它可能会失败。因此,日志例程跟踪它们被调用的“深度”,如果是递归日志调用,则切换内存分配策略(它们在堆栈上而不是在堆上进行分配)
每当日志记录例程收到错误消息并希望记录错误时,就会发生一些非常糟糕的事情,因此尝试使用另一种机制记录然后退出是有意义的
所以你可能只是看到了真正问题的一个遥远的症状。您可以使用ltrace(1)
来尝试发现问题,或者您可以启用核心转储(ulimit-c unlimited
),并尝试使用gdb的bt
命令来查找导致程序崩溃的调用链。请注意,如果您正在注册自定义处理程序,对g_*日志例程的递归调用也可能发生(使用g_log_set_handler
)并且该处理程序(或其被调用方之一)尝试通过调用g_*例程来记录错误
还要注意,glib认为任何递归都应该是致命的(即使只有一级深度的非无限)。对于sarnold关于内部故障递归的回答中描述的情况,这当然是有意义的,但在试图解决自定义处理程序重复出现的问题时,这可能并不明显。因此,glib早在对g_*的第一次递归调用时就检测到递归;它甚至无法检查您的自定义处理程序是否已连接。因此,您永远不会看到对处理程序的递归调用。所有这一切都意味着,在处理程序的主体中小心地注销处理程序(以及类似的事情)是徒劳的
您必须绝对确保自定义处理程序的调用堆栈中没有任何东西会调用g_*例程(如果处理程序调用外部代码,并尝试将日志消息传递到远程目标或其他复杂的事情,那么这可能会变得棘手)