分段故障加载字典。它是由calloc,sys / stat.h还是其他原因造成的?

时间:2014-10-08 18:37:38

标签: c dictionary dynamic-arrays trie calloc

此函数应该将字典加载到trie中。我想知道字典文件有多大,所以我可以同时calloc所有内存。这样做的原因是所有内存都靠近在一起,因此可以利用有助于加速搜索的硬件。为此,我找到了2种方法的建议。其中之一就是使用您将在我的代码中看到的sys/stat.h

当我运行此代码时,我收到一个"分段错误"我知道这意味着我正在尝试访问我没有获得许可的内存。通过使用GDB,我发现分段错误发生在第116行(又名:读取&#34的行;否则如果(cur-> children [key] == NULL)")我发现当时密钥中的值是12.起初我认为问题是我使用callocsys/stat.h,因为这些是我所知道的最少关于我使用的两件事。然而,我研究得越多,这似乎就越不可能。如果它不是其中之一那么我甚至不知道在哪里看。

贝娄只是我认为相关的代码:

#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sys/stat.h>

#include "dictionary.h"

typedef struct node
{
    bool end[26]; 

    struct node* children[26]; 
} node;

node* start;

int key;
int last;
int dic_count;

bool load(const char* dictionary)
{
    struct stat s;
    stat(dictionary, &s);
    int size = s.st_size;

    dic_count = 0;

    int z = 1;

    FILE* dic = fopen(dictionary, "r");
    if (dic == NULL)
    {
        return false;
    }

    start = calloc(size, sizeof(node));

    if (start == NULL)
    {
        return false;
    }

    int l = 0;
    int d;

    node* cur = &start[0];

    while (0 != (d = fgetc(dic)))
    {
        int d = fgetc(dic);

        if (l > 0)
        {
            last = key;
        }

        l = 1;

        key = d - 'a';

        if (d == '\n')
        {
            cur->end[last] = true;
            cur = &start[0];
            dic_count++;
        }
        else if (cur->children[key] == NULL)
        {
            node* new = &start[z];

            cur->children[key] = new;

            z++;

            if (cur->children[key] == NULL)
            {
                return false;
            }

            cur = cur->children[key];
        }
        else
        {
            cur = cur->children[key];
        }
    }
    return true;
}

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:3)

您确定您的文件包含二进制0吗?如果您尝试读取直到文件结尾,请针对EOF测试fgetc结果,而不是0.否则您的循环永远不会终止。

除此之外,您只处理每隔一个字符。

按要求扩展

来自man fgetc

  

fgetc(),getc()和getchar()将读取的字符作为无符号的char转换为文件末尾的错误或EOF或错误

您可能会将其与fgets返回值混淆。

while ((ch = fgetc(fp)) != EOF)

安然无恙。再次,可能混淆的根源是

的不健全
while (!feof(fp))

现在,关于未处理的字符:你写了

    while (0 != (d = fgetc(dic)))
    {
        int d = fgetc(dic);

代码读取while表达式中的字符,将其与0进行比较,然后读取(下一个)字符。第一个角色丢失了。