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

全局指针在函数/递归中无法访问结构体致程序核心转储求助

C语言字典实现核心转储与节点指针Nil问题修复

问题复盘

实现字典功能时出现以下异常:

  • 全局指针调用函数能传递地址,但访问下一个节点时返回(nil)
  • generate函数内打印节点指针正常,但程序在第231行(any->is_word = 1处)核心转储
  • 测试length=1、tmp_word="a"场景时,第214行any->character[0]输出nil
  • 调整全局变量逻辑后问题未解决

核心问题根源

  1. generate函数误用全局root变量:递归创建trie节点时,每次都给全局root赋值,导致上层节点的character[i]指针被后续递归的malloc覆盖,最终上层节点的子节点指针指向错误地址,甚至变成野指针。
  2. assign函数硬编码索引:处理单词时固定访问any->character[1],不符合字母映射逻辑,导致访问错误的空节点。
  3. 语法错误:assign函数中any->is_word = 1末尾缺少分号,触发未定义行为,直接引发核心转储。
  4. hash_函数内存管理错误:每次处理完单词后free(tmp_word),但后续循环未重新分配内存,导致后续使用野指针。
  5. 递归函数未传递返回值:check_trie、check_trie_v2、check_hash的递归调用没有返回结果,导致判断逻辑失效。

具体修复方案

修复generate函数

将全局root替换为局部变量,避免递归时覆盖上层指针:

trie *generate(int times)
{
    trie *node = malloc(sizeof(trie));
    node->next = NULL;
    node->is_word = false; // 初始化is_word为false

    if (times > 0)
    {
        for (int i = 0; i < nodes; i++)
        {
            node->character[i] = generate(times - 1);
        }
    }
    else
    {
        for (int i = 0; i < nodes; i++)
        {
            node->character[i] = NULL;
        }
        node->next = malloc(sizeof(hash_table));
        node->next->next = NULL;
    }

    return node;
}

修复assign函数

补充分号,并根据字符计算正确索引:

void assign(trie *any, int length, int index, char *tmp_word)
{
    printf("%p\n", any);
    printf("%p\n", any->character[0]);

    if (length != 0)
    {
        int idx;
        if (tmp_word[index] != '\'')
        {
            idx = tolower(tmp_word[index]) - 'a'; // 统一转小写计算索引
            assign(any->character[idx], length - 1, index + 1, tmp_word);
        }
        else
        {
            idx = 26;
            assign(any->character[idx], length - 1, index + 1, tmp_word);
        }
    }
    else
    {
        any->is_word = true; // 只有length==0时标记为单词节点
    }
    return;
}

修复hash_函数的内存管理

每次循环重新分配tmp_word,避免野指针:

void hash_(trie *any)
{
    char *tmp_word;
    char c;

    for (int i = 0; dict_word[i] != '\0'; i++)
    {
        if (dict_word[i] == '\n')
        {
            continue;
        }
        tmp_word = calloc(1, 46);
        int j = 0;
        while (dict_word[i] != '\n' && dict_word[i] != '\0')
        {
            c = dict_word[i];
            tmp_word[j++] = c;
            i++;
        }
        tmp_word[j] = '\0'; // 手动添加字符串结束符
        int length = strlen(tmp_word);

        if (length <= heigth)
        {
            assign(root, length, 0, tmp_word);
        }
        else
        {
            assign_v2(root, heigth, 0, tmp_word);
        }
        free(tmp_word);
        count_words++; // 统计单词数量
    }
}

修复递归函数的返回值传递

bool check_trie(const char *word, int length, trie *any, int index)
{
    if (any == NULL) return false; // 空节点直接返回false
    if (length != 0)
    {
        int idx;
        if (word[index] == '\'')
        {
            idx = 26;
            return check_trie(word, length - 1, any->character[idx], index + 1);
        }
        else
        {
            idx = tolower(word[index]) - 'a';
            return check_trie(word, length - 1, any->character[idx], index + 1);
        }
    }
    return any->is_word;
}

bool check_trie_v2(const char *word, int length, trie *any, int index)
{
    if (any == NULL) return false;
    if (length != 0)
    {
        int idx;
        if (word[index] == '\'')
        {
            idx = 26;
            return check_trie_v2(word, length - 1, any->character[idx], index + 1);
        }
        else
        {
            idx = tolower(word[index]) - 'a';
            return check_trie_v2(word, length - 1, any->character[idx], index + 1);
        }
    }
    return check_hash(word, any->next);
}

bool check_hash(const char *word, hash_table *any)
{
    if (any == NULL) return false;
    if (strcmp(word, any->word) == 0)
    {
        return true;
    }
    return check_hash(word, any->next);
}

修复assign_v2b函数的链表插入逻辑

原代码修改形参不会影响实参,需通过指针修改:

void assign_v2b(hash_table **any, char *tmp_word)
{
    hash_table *new_node = malloc(sizeof(hash_table));
    strcpy(new_node->word, tmp_word);
    new_node->next = *any;
    *any = new_node;
}
// 调用时改为:assign_v2b(&any->next, tmp_word);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 19:01:59