You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用g_log_structured向Linux系统日志输出时出现内存泄漏求助

Glib g_log_structured 内存泄漏与段错误问题排查

我在Ubuntu系统上使用Glib 2.76.1实现向系统日志(journald)输出结构化日志,测试了三种实现方式后发现,调用g_log_structured()时频繁出现内存访问错误和内存泄漏,而g_log_structured_array()和直接调用g_log_writer_journald()的方式都能正常工作。

相关代码如下:

#define G_LOG_USE_STRUCTURED
#define G_LOG_DOMAIN "MyDomain"

#include <glib.h>
#include <stdio.h>

int main(int argc, char *argv[]) 
{
   g_log_set_writer_func (g_log_writer_journald, NULL, NULL);

/*  regularly leads to a memory leak.
    g_log_structured (G_LOG_DOMAIN,
                   G_LOG_LEVEL_DEBUG,
                   "CODE_FILE", "mysource.c",
                   "CODE_LINE", 312,
                   "MESSSAGE_ID", "06d4df59e6c24647bfe69d2c27ef0b4e",
                   "MESSAGE", "You have %d eggs", 12 + 2);
*/

/* The following log message will go to journald */
        const GLogField fields[] = {
               {"MESSAGE", "This is the message", -1},
               {"EIGENES_FELD", "mysource.c", -1},
               {"STATUS", "3",-1},
        };

        // works        
        g_log_structured_array (G_LOG_LEVEL_DEBUG, fields,G_N_ELEMENTS (fields));
        
        // works
        GLogWriterOutput result = g_log_writer_journald (
                                 G_LOG_LEVEL_INFO,
                                 fields,
                                 G_N_ELEMENTS(fields),
                                 NULL); 
    return 0;
}

出现的段错误日志:

Okt 19 14:44:05 holger kernel: a.out[12281]: segfault at 138 ip 00007fe6b6b7401d sp 00007ffe746157e8 error 4 in libc.so.6[7fe6b6a22000+178000] likely on CPU 1 (core 1, socket 0)
Okt 19 14:44:05 holger kernel: Code: 00 00 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 89 f8 48 89 fa c5 f9 ef c0 25 ff 0f 00 00 3d e0 0f 00 00 0f 87 33 01 00 00 <c5> fd 74 0f c5 fd d7 c1 85 c0 74 57 f3 0f bc c0 c5 f8 77 c3 66 66

问题原因与处理经验

  • 参数格式错误是核心问题
    注释的g_log_structured()调用存在两处致命错误:

    1. 字段名拼写错误:MESSSAGE_ID多写了一个S,正确应为MESSAGE_ID;
    2. MESSAGE字段的参数传递逻辑错误:g_log_structured()的可变参数是键值对序列,而非printf的格式化参数。你传递的"You have %d eggs", 12 + 2会被解析为"You have %d eggs"作为键、整数14作为值的无效键值对,直接破坏函数内部的参数解析逻辑,引发内存访问越界和段错误。
  • 内存泄漏由参数错误引发
    参数解析混乱会导致Glib内部内存管理逻辑出错,进而触发内存泄漏。修复参数格式后,这类内存泄漏通常会自动消失。

  • 修复后的示例代码
    修正参数后的g_log_structured()调用如下:

    g_log_structured (G_LOG_DOMAIN,
                      G_LOG_LEVEL_DEBUG,
                      "CODE_FILE", "mysource.c",
                      "CODE_LINE", GINT_TO_POINTER(312),
                      "MESSAGE_ID", "06d4df59e6c24647bfe69d2c27ef0b4e",
                      "MESSAGE", "You have 14 eggs",
                      NULL);
    

    若要使用格式化字符串,需提前拼接完成或用GVariant传递:

    gchar *msg = g_strdup_printf("You have %d eggs", 12 + 2);
    g_log_structured (G_LOG_DOMAIN,
                      G_LOG_LEVEL_DEBUG,
                      "CODE_FILE", "mysource.c",
                      "CODE_LINE", GINT_TO_POINTER(312),
                      "MESSAGE_ID", "06d4df59e6c24647bfe69d2c27ef0b4e",
                      "MESSAGE", msg,
                      NULL);
    g_free(msg);
    

    关键注意点:

    • 整数类型字段值必须用GINT_TO_POINTER()包装;
    • 可变参数必须以NULL结尾,标记键值对序列结束;
    • 不支持直接传递printf式的格式化参数,需提前处理字符串。
  • 版本相关问题参考
    Glib 2.76.x确实存在少量结构化日志的边界场景bug,但大多与参数错误相关。若修复参数后仍有问题,建议升级到Glib 2.78及以上版本,官方在后续版本中修复了部分内存管理相关的问题。

内容的提问来源于stack exchange,提问作者Holger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 02:35:12