【问题标题】:Dynamic array of strings动态字符串数组
【发布时间】:2012-11-13 01:38:23
【问题描述】:

我必须动态分配单词数组。单词存储在由可变数量的空白字符分隔的文件中。我不知道文件中有多少个单词,它们可以有可变长度。

我有这个代码:

void readWord(FILE* stream, char *word, char first_c) {

    word[0] = first_c;
    char val;
    int wlen = 1;
    // isWhitespac is my function - tests if char is blank or '\n'
    while ((val = fgetc(stream)) != EOF && isWhitespace(val) == 0) {
        wlen++;
        word = realloc(word, (wlen+1) * sizeof (char));

        word[wlen-1] = val;    

    }
    word[wlen] = '\0';
}

int readList(const char *file) {

    FILE* f;
    char **arr;
    char val;
    int wcount = 0;

    arr = malloc(sizeof (char*));
    f = fopen(file, "r");

    while (fscanf(f, " %c", &val) == 1) {
        wcount++;
        arr = realloc(arr, wcount * sizeof (char *));

        arr[wcount - 1] = malloc(sizeof (char));  

        readWord(f, arr[wcount-1], val); 
        printf("%s\n", arr[wcount-1]);

    }


    for (int i = 0; i < wcount; ++i) {
        free(arr[i]);
    }

    free(arr);

    fclose(f);
    return 0;
}

它似乎工作正常,它读取一个打印所有单词。但是当我用 Valgrind 运行程序时,错误太多,我找不到。有人可以帮我吗? (我知道我必须测试 malloc 和其他是否正常,这只是一个测试函数。)

Valgrind 日志很长,我也应该贴出来吗?

【问题讨论】:

  • 如果这行得通,唯一可行的方法是让您阅读的字长方便地适合单页分配,因此realloc 永远不必移动数据。你通过而不是地址传递你原来的malloc指针,所以如果你的readWord中的realloc确实必须分配一个新页面并移动数据,你将有一个悬空指针回到readList,一旦readWord 退出,就会从新的word 指针泄漏内存。从这个意义上说,这段代码绝对不是“工作正常”。剩下的交给你和 valgrind。
  • 您应该将您的代码缩减为一些小的东西以隔离问题。但话虽如此,您并没有以安全的方式使用realloc。请参阅有关此主题的 C 常见问题解答:c-faq.com/malloc/realloc.html

标签: c string malloc realloc


【解决方案1】:

其中一个问题是您在 readWord 中执行 realloc。如果 realloc 分配了一个新缓冲区并且不只是扩展当前缓冲区,那么您的代码将崩溃(您将双重释放指针),这就是 Valgrind 的选择。为了解决这个问题,我将重写代码,使其返回一个指针而不是 void。

char * readWord(FILE* stream, char *word, char first_c) {
    word[0] = first_c;
    char val;
    int wlen = 1;
    // isWhitespac is my function - tests if char is blank or '\n'
    while ((val = fgetc(stream)) != EOF && isWhitespace(val) == 0) {
      wlen++;
      word = realloc(word, (wlen+1) * sizeof (char));
      word[wlen-1] = val;
    }
    word[wlen] = '\0';
    return word;
}

然后将readList中的循环改成这样:

while (fscanf(f, " %c", &val) == 1) {
  wcount++;
  arr = realloc(arr, wcount * sizeof (char *));
  arr[wcount-1]=malloc(sizeof(char));
  arr[wcount - 1] = readWord(f, arr[wcount-1],  val);
  printf("%s\n", arr[wcount-1]);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-27
    • 2020-12-09
    • 1970-01-01
    • 2019-04-11
    • 1970-01-01
    相关资源
    最近更新 更多