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

C语言uthash添加整型数组为哈希键时触发段错误的问题咨询

问题根因

你的段错误和用int数组作为键本身无关,核心是uthash的用法存在错误,同时有会触发随机崩溃的隐患:

  • 最常见的崩溃诱因:HASH_ADD系列宏不会主动校验键是否重复,如果你插入两个键完全一致的节点,会直接破坏哈希表内部的双向链表结构,后续任意哈希操作都可能触发段错误,很多人调试时会误将崩溃位置定位到相邻的代码行。
  • 用法不规范问题:uthash所有操作宏的第二个参数必须是固定的哈希表头指针,该指针初始值必须为NULL,uthash会在插入第一个节点、删除最后一个节点时自动修改它的值,不要手动给这个指针赋值非节点地址,所有增删查操作都要传入这个头指针。
  • 补充:固定长度数组作为键的写法本身合法,uthash默认会用memcmp做键比较、内置字节哈希函数计算哈希值,不需要额外自定义哈希/比较逻辑,传入sizeof(int)*26作为键长的写法是正确的。
修正后的可运行代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "uthash.h"

struct record
{
  int key[26];
  UT_hash_handle hh;
};

int main() {
    // hash_head是固定的哈希表头指针,初始必须为NULL
    struct record *hash_head = NULL, *tmp = NULL, *res = NULL;
    struct record find;

    // 添加第一条记录
    tmp = (struct record *)malloc(sizeof(struct record));
    memset(tmp, 0, sizeof(struct record));
    tmp->key[0] = 2;
    tmp->key[3] = 3;
    tmp->key[7] = 7;
    // 插入前先查重,避免破坏表结构
    HASH_FIND(hh, hash_head, tmp->key, sizeof(int)*26, res);
    if (res == NULL) {
        HASH_ADD(hh, hash_head, key, sizeof(int)*26, tmp);
    } else {
        free(tmp); // 键重复时释放新建节点,避免内存泄漏
    }

    // 添加第二条记录
    tmp = (struct record *)malloc(sizeof(struct record));
    memset(tmp, 0, sizeof(struct record));
    tmp->key[0] = 2;
    tmp->key[3] = 3;
    tmp->key[7] = 8;
    HASH_FIND(hh, hash_head, tmp->key, sizeof(int)*26, res);
    if (res == NULL) {
        HASH_ADD(hh, hash_head, key, sizeof(int)*26, tmp);
    } else {
        free(tmp);
    }

    // 查找记录
    memset(&find, 0, sizeof(struct record));
    find.key[0] = 2;
    find.key[3] = 3;
    find.key[7] = 7;
    HASH_FIND(hh, hash_head, find.key, sizeof(int)*26, res);
    if (res) {
        printf("found, key[7] = %d\n", res->key[7]);
    } else {
        printf("Not found\n");
    }

    // 用完释放所有节点,避免内存泄漏
    struct record *cur, *next;
    HASH_ITER(hh, hash_head, cur, next) {
        HASH_DEL(hash_head, cur);
        free(cur);
    }
    return 0;
}
uthash使用注意点
  • 不同键类型优先用对应宏减少出错:键为int类型用HASH_ADD_INT,键为'\0'结尾的字符串用HASH_ADD_STR,这两个不需要手动传入键长;只有固定长度结构体、数组等二进制块作为键时,才用通用HASH_ADD,必须准确传入键的字节长度。
  • 新节点malloc后必须将整个内存块清零,保证UT_hash_handle成员初始值全为0,否则插入时会因为内部脏值触发崩溃。
  • 不要手动修改已加入哈希表节点的UT_hash_handle成员,不要不经过HASH_DEL就直接释放表中节点,否则会破坏表结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 18:15:51