首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >当我在Linux中运行时,为什么这段代码不断给我一个Segfault错误?

当我在Linux中运行时,为什么这段代码不断给我一个Segfault错误?
EN

Stack Overflow用户
提问于 2019-04-08 01:07:02
回答 1查看 0关注 0票数 0

所以我正在尝试创建一个接收文本文件的函数,该文件包含由换行符分隔的一堆单词,并将文本文件读入char**数组。

当我在Windows上的netbeans中运行此代码时,它工作正常,但如果我在Linux中运行它,我会收到分段错误错误。

代码语言:javascript
复制
// globals
FILE *words_file;
char **dic;
int num_words = 0;

void read_to_array() {
    words_file = fopen("words.txt", "r");
    char *line = NULL;
    int i = 0;
    size_t len = 0;
    dic = (char **)malloc(99999 * sizeof(char *));

    // read dic to array
    while (getline(&line, &len, words_file) != -1) {
        dic[i] = (char*)malloc(len);
        strcpy(dic[i], line);

        // get rid of \n after word
        if (dic[i][strlen(dic[i]) - 1] == '\n') {
            dic[i][strlen(dic[i]) - 1] = '\0';
        }
        ++i; 
        num_words++;
    }
    //printf("%s", dic[i][strlen(dic[i]) - 1]);  //testing 
    fclose(words_file);
    dic[i] = NULL;
}

我在这里错过了什么?

EN

回答 1

Stack Overflow用户

发布于 2019-04-08 10:26:52

您的程序中存在一些可能导致您观察到的未定义行为的问题:

  • 您不测试文件是否已成功打开,如果文件不在您期望的位置或具有不同的名称,则会导致未定义的行为。
  • 您不限制读入数组的行数,如果文件包含超过99998行,则会导致未定义的行为/usr/share/dict/words,例如,在我的系统中可能是linux 中的139716行。

您的内存分配方案不是最理想的但是正确的:您应该分配副本之前计算单词的长度并去除换行符。编码时,您分配的内存太多。但是你应该line在返回之前自由read_to_array,你应该避免使用全局变量。

这是一个修改版本:

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char **read_to_array(const char *filename, int *countp) {
    FILE *words_file;
    char *line = NULL;
    size_t line_size = 0;
    char **dic = NULL;
    int dic_size = 0;
    int i = 0;

    words_file = fopen(filename, "r");
    if (words_file == NULL) {
        fprintf(stderr, "cannot open dictionary file %s\n", filename);
        return NULL;
    }

    dic_size = 99999;
    dic = malloc(dic_size * sizeof(char *));
    if (dic == NULL) {
        fprintf(stderr, "cannot allocate dictionary array\n");
        fclose(words_file);
        return NULL;
    }

    // read dic to array
    while (getline(&line, &line_size, words_file) != -1) {
        size_t len = strlen(line);
        /* strip the newline if any */
        if (len > 0 && line[len - 1] == '\n') {
            line[--len] = '\0';
        }
        if (i >= dic_size - 1) {
            /* too many lines: should reallocate the dictionary */
            fprintf(stderr, "too many lines\n");
            break;
        }
        dic[i] = malloc(len + 1);
        if (dic[i] == NULL) {
            /* out of memory: report the error */
            fprintf(stderr, "cannot allocate memory for line %d\n", i);
            break;
        }
        strcpy(dic[i], line);
        i++;
    }
    dic[i] = NULL;
    *countp = i;
    fclose(words_file);
    free(line);
    return dic;
}

int main(int argc, char **argv) {
    const char *filename = (argc > 1) ? argv[1] : "words.txt";
    int num_words;
    char **dic = read_to_array(filename, &num_words);
    if (dic != NULL) {
        printf("dictionary loaded: %d lines\n", num_words);
        while (num_words > 0)
            free(dic[--num_words]);
        free(dic);
    }
    return 0;
}

输出:

代码语言:javascript
复制
chqrlie> readdic /usr/share/dict/words
too many lines
dictionary loaded: 99998 lines
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100006551

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档