c- sysmalloc断言问题

时间:2017-11-20 20:21:07

标签: c trie

我希望有人可以帮我理解我在哪里出错了。我正在实施一个检查拼写正确性的程序。在这个过程中,我使用trie数据结构将字典文本文件加载到内存中以检查单词。

总的来说,它似乎按预期运行,但是当加载最长的单词时,即加入肺炎微量纤维细胞病,我会遇到很多问题。我不明白为什么,但首先让我提出一些代码 -

/**
* Loads dictionary into memory. Returns true if successful else false.
*/
bool load(const char *dictionary)
{
    FILE *dict = fopen(dictionary, "r");
    if (dict == NULL)
    {
        fprintf(stderr, "Could not open %s dictionary file.\n", dictionary);
        return false;
    }

    // Initialise the root t_node
    root = (t_node *) malloc(sizeof(t_node));
    if (root == NULL)
    {
        fprintf(stderr, "Could not allocate memory to trie structure.\n");
        return false;
    }

    // Set all current values in root to NULL and is_word to false
    for (int i = 0; i < ALPHA_SIZE; i++)
    {
        root->branch[i] = NULL;
    }
    root->is_word = false;


    while (1)
    {
        // Create char aray to hold words from .txt dictionary file once read 
        char *word = (char *) malloc((LENGTH + 1) * sizeof(char));

        if (fscanf(dict, "%s", word) == EOF)
        {
            free(word);
            break;
        }

        t_node *cursor = root;
        int len = strlen(word) + 1;
        for (int i = 0; i < len; i++)
        {
            if (word[i] == '\0')
            {
                cursor->is_word = true;
                cursor = root;
                word_count++;
            }

            else
            {
                int index = (word[i] == '\'') ? ALPHA_SIZE - 1 : tolower(word[i]) - 'a';
                if (cursor->branch[index] == NULL)
                {
                    cursor->branch[index] = (t_node *) malloc(sizeof(t_node));
                    for (int j = 0; j < ALPHA_SIZE; j++)
                    {
                        cursor->branch[index]->branch[i] = NULL;
                    }
                    cursor->branch[index]->is_word = false;
                }
            cursor = cursor->branch[index];
            }
        }

        free(word);
    }

    fclose(dict);
    return true;
}

这是我将字典加载到内存中的整个函数。作为参考,我定义了trie结构并在此函数之前创建了根。 LENGTH定义为45以说明可能的最长单词。而ALPHA_SIZE是27包括小写字母加撇号。

正如我已经说过所有其他较短的单词,这个功能运作良好。但是,使用最长的单词,函数通过大约一半的单词起作用,在遇到sysmalloc断言问题然后中止之前,先起作单词变量的索引29。

我试图找到这里发生的事情,但我能看到的最多是它在 -

cursor->branch[index] = (t_node *) malloc(sizeof(t_node));

一旦到达第29个单词索引,但之前没有其他索引。我能找到的所有其他帖子都与提供此错误的函数有关,而这些函数根本不起作用,而不是大部分时间都有异常。

任何人都可以看到我不能做的以及我在此代码中犯的错误是什么?我感谢您的帮助,感谢大家花时间考虑我的问题。

*更新*

首先,我要感谢所有人的帮助。看到有多少人对我的问题作出回应以及他们做得多快,我感到非常惊喜!我不能对你们所有人的帮助表示感谢。特别是Basile Starynkevitch给了我很多信息并提供了很多帮助。

我非常尴尬地说,我已经找到了我的问题,而且在转向SO之前,我应该抓住一段时间。因此,我必须为使用每个人的时间而道歉,因为这些事情太愚蠢了。我的问题在这里撒谎 -

else
{
    int index = (word[i] == '\'') ? ALPHA_SIZE - 1 : tolower(word[i]) - 'a';
    if (cursor->branch[index] == NULL)
    {
        cursor->branch[index] = (t_node *) malloc(sizeof(t_node));
        for (int j = 0; j < ALPHA_SIZE; j++)
        {
            cursor->branch[index]->branch[j] = NULL; // <<< PROBLEM WAS HERE
        }
        cursor->branch[index]->is_word = false;
    }
    cursor = cursor->branch[index];
}

在我的代码中,我最初有&#39; cursor-&gt; branch [index] - &gt; branch [i] = NULL&#39;我在哪里迭代&#39; int j&#39;在那个循环中,不是我......

Sooooo再次感谢大家的帮助!对于格式错误的问题,我很抱歉,将来我会更好地遵守SO指南。

1 个答案:

答案 0 :(得分:0)

  char *word = (char *) malloc((LENGTH + 1) * sizeof(char));

后面没有malloc失败的测试;你需要添加:

  if (!word) { perror("malloc word"); exit(EXIT_FAILURE); }

          if (fscanf(dict, "%s", word) == EOF)

因为在fscanf指针上使用%s NULL是错误的(undefined behavior,可能)。

BTW,最新版本的fscanf(或dynamic memory TR)接受%ms说明符,以便在阅读时分配字符串。在那些系统上你可以:

 char*word = NULL;
 if (fscanf(dict, "%ms", &word) == EOF))
   break;

有些系统有getline,请参阅this

最后,编译所有警告和调试信息(gcc -Wall -Wextra -g与GCC),改进代码以获取警告,并使用调试器gdbvalgrind

BTW 肺炎微血管病毒性病毒有45个字母。你需要一个额外的字节来终止NUL(否则你有一个buffer overflow)。所以你的LENGTH至少应该是46(我建议选择稍微大一点的东西,也许是64;实际上我建议系统地使用 C dynamic memory allocation并避免硬编码这样的限制和在robust style之后的GNU coding standards更多代码。