c - 段错误加载字典。它是由 calloc、sys/stat.h 还是其他原因引起的?

标签 c dictionary dynamic-arrays trie calloc

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

当我运行这段代码时,我收到一个“段错误”,我知道这意味着我正在尝试访问我没有权限的内存。通过使用 GDB 我发现段错误发生在第 116 行(又名:读取“else if (cur->children[key] == NULL)”的行)我发现 key 中的值在那时间是 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;
}

非常感谢任何帮助。

最佳答案

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

除此之外,您只处理每个第二个字符。

按要求扩展:

来自 man fgetc:

fgetc(), getc() and getchar() return the character read as an unsigned char cast to an int or EOF on end of file or error

您可能将它与 fgets 返回值混淆了。

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

安然无恙。同样,可能造成混淆的原因是

while (!feof(fp))

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

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

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

关于c - 段错误加载字典。它是由 calloc、sys/stat.h 还是其他原因引起的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26264055/

相关文章:

在 C 中创建字符串值并将其添加到二维数组

c - 在枚举声明中使用数据类型

c++ - 为什么结构的 sizeof 不等于每个成员的 sizeof 之和?

arrays - 在将动态数组作为变量参数传递之前是否可以强制转换?

c - 如何在多个 strncmp 以下进行优化?

performance - Python 3.3 在大循环期间变慢

python - 如何将不带引号的字符串转换为python中的字典

c# - 如何将项目添加到字典 "Parallel loop safe"

arrays - 如何在Solidity中创建动态内存数组?

delphi - 动态数组是否支持非零下限(为了 VarArrayCreate 兼容性)?