【问题标题】:realloc, for string array in Crealloc,用于 C 中的字符串数组
【发布时间】:2018-11-05 12:30:36
【问题描述】:

当你想将可变大小的单词添加到字符串数组时,是否有正确的方法来使用 realloc?我遇到了分段错误。 请告诉我有什么问题

// This function puts every word found in a text file, to a String array, **words
char **concordance(char *textfilename, int *nwords){
    FILE * fp;
    char *fileName = strdup(textfilename);
    fp = fopen(fileName, "r");
    if(fp == NULL) {
        perror("fopen");
        exit(1);
    }
    char **words = malloc(sizeof(char));
    // char **words = NULL

    char line[BUFSIZ];
    while(fgets(line, sizeof(line), fp) != NULL){
        char *word = strdup(line);
        word = strtok(word, " ");
        do{
            words = realloc(words, (*nwords+1) * sizeof(char(*)));
            words[*nwords] = word;
        } while((word = strtok(NULL, " ")) != NULL);
    }
    return words;
}


int main(int argc, const char * argv[]) {
    int *nwords = malloc(sizeof(int));
    nwords = 0;
    concordance("test.txt", nwords);
}

【问题讨论】:

  • char **words = malloc(sizeof(char)); 在我看来很可疑
  • 您是否使用过调试器(gdb 或 valgrind)来检查您的程序?!
  • char **words 应该分配给指针的大小和要存储的最大指针数,例如char **words = malloc(sizeof(char *)*1000); 最多 1000 个指针。
  • 安东尼奥。我试过了,还是不行
  • 除非你真的知道自己在做什么,否则你真的不应该使用strtok(),因为它会修改你正在扫描的字符串,用空值替换分隔符。

标签: c pointers realloc


【解决方案1】:

您似乎以错误的方式将nwords 初始化为0。由于您已将其声明为指针,因此您无法直接访问它。相反,您应该使用取消引用运算符*

main 函数中进行以下更改

*nwords = 0; 而不是nwords = 0;

nwords = 0nwords 指向的位置修改为地址为0 的位置,您无权访问且无法分配。

警告:

  1. 最好不要在同一个指针上执行realloc,如果realloc失败会使指向位置NULL,导致之前存在的数据丢失。相反,正如@David 建议的那样,您可以使用一个临时变量到realloc 内存,然后检查它是否不是NULL,然后将其内容分配给words 指针。
    //your code
    char *tmp = realloc(words, /* new size*/);
    if(tmp != NULL)
        words = tmp;
    // your code
  1. 在使用realloc 时,您通常使用它来分配数据块,而不是单个位置。

【讨论】:

  • 查看其他答案下关于“从不使用指针本身重新分配......”的评论。指出潜在的错误总是好的。
【解决方案2】:

当您初始化nwords 的值时,您正在覆盖它的指针地址,而不是它的值。

此外,正如评论者所说,char **words = malloc(sizeof(char)); 行不正确。但是您总是重新分配变量words,因此代码仍然可以按预期工作。为了让它超级安全,你应该把它改成char **words = malloc(sizeof(char*));

我使用*nwords = 0; 行,现在它按预期工作。

#define BUFSIZ 1000
#include<stdio.h>
// This function puts every word found in a text file, to a String array, **words
char **concordance(char *textfilename, int *nwords){
  FILE * fp;
  char *fileName = strdup(textfilename);
  fp = fopen(fileName, "r");
  if(fp == NULL) {
    perror("fopen");
    exit(1);
  }
  char **words = malloc(sizeof(char));
  // char **words = NULL

  char line[BUFSIZ];
  while(fgets(line, sizeof(line), fp) != NULL){
    char *word = strdup(line);
    word = strtok(word, " ");
    printf("word='%s'\n",word);
    do{
      *nwords=*nwords+1;
      printf("nwords=%d\n",*nwords);
      words = realloc(words, (*nwords+1) * sizeof(char(*)));
      words[*nwords] = word;
    } while((word = strtok(NULL, " ")) != NULL);
  }
  return words;
}


int main(int argc, const char * argv[]) {
  int *nwords = malloc(sizeof(int));
  *nwords = 0;
  concordance("test.txt", nwords);
}

【讨论】:

  • char **words = malloc(sizeof(char)); 无法按预期工作。
  • 它只是给出一个指向单个字节的指针。然后代码总是用正确数量的单词重新分配它。这在哲学上并不正确,但确实有效。
  • 永远不要 realloc 使用指针本身。如果realloc 失败(确实如此),它会返回NULL 覆盖您的地址,从而防止原始块被释放,从而造成内存泄漏。使用临时指针,例如void *tmp = realloc (words, (nwords + 1) * sizeof *words); 然后验证 tmp != NULL。 (请注意,每次迭代通过 1 指针重新分配效率非常低,最好在块中分配多个指针并跟踪使用的数量和realloc 当你用完时)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-27
  • 2016-08-12
  • 1970-01-01
  • 2013-04-19
  • 2012-12-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多