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

为何我的代码内存分配超出预期?Valgrind检测到额外分配与释放

哈希表代码的Valgrind额外分配/释放问题

我编写了一段创建哈希表的C语言代码:

typedef struct hash_node_s
{
    char *key;
    char *value;
    struct hash_node_s *next;
} hash_node_t;

typedef struct hash_table_s
{
    unsigned long int size;
    hash_node_t **array;
} hash_table_t;

hash_table_t *hash_table_create(unsigned long int size)
{
    hash_table_t *table;

    table = malloc(sizeof(hash_table_t));

    if (!table)
    {
        printf("failed to create table");
        return (NULL);
    }

    table->size = size;
    table->array = malloc(sizeof(hash_node_t *) * size);

    if (!table->array)
    {
        printf("failed to create table->array");
        free(table);
        return (NULL);
    }

    return (table);
}

int main(void)
{
    hash_table_t *ht;

    ht = hash_table_create(1024);
    printf("%p\n", (void *)ht);

    return (EXIT_SUCCESS);
}

原本预期运行时仅会产生2次内存分配、0次释放,但使用Valgrind 3.18.1检测时,得到如下结果:

root@anon# valgrind ./a
==1374== Memcheck, a memory error detector
==1374== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1374== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==1374== Command: ./a
==1374==
0x4a8c040
==1374==
==1374== HEAP SUMMARY:
==1374==     in use at exit: 8,208 bytes in 2 blocks
==1374==   total heap usage: 3 allocs, 1 frees, 9,232 bytes allocated
==1374==
==1374== LEAK SUMMARY:
==1374==    definitely lost: 16 bytes in 1 blocks
==1374==    indirectly lost: 8,192 bytes in 1 blocks
==1374==      possibly lost: 0 bytes in 0 blocks
==1374==    still reachable: 0 bytes in 0 blocks
==1374==         suppressed: 0 bytes in 0 blocks
==1374== Rerun with --leak-check=full to see details of leaked memory
==1374==
==1374== For lists of detected and suppressed errors, rerun with: -s
==1374== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

请问这额外的1次分配与1次释放来自哪里?我已尝试--leak-check=full等选项,但仍未找到原因。


解答

这额外的1次分配和1次释放来自C标准库的内部初始化操作,触发点是你代码中的printf调用:

  • 当程序第一次调用printf时,C标准库会为标准输出的缓冲区分配一块内存(对应那1次额外分配)
  • 在程序正常退出前,标准库会自动释放这块缓冲区(对应那1次释放)
  • 哪怕错误分支的printf没有执行,主函数里的printf("%p\n", (void *)ht)也会触发这个初始化逻辑

可以通过以下方式验证:

  • 注释掉代码中所有printf调用,重新编译后用Valgrind检测,堆统计会变成2次分配、0次释放,与预期一致
  • 仅保留主函数里的printf,依然会出现那1次额外的分配和释放

Valgrind的堆统计会包含标准库内部的内存操作,这属于正常的库行为,并非你的代码存在问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 21:17:36