【问题标题】:free of array of strings crashes with "A heap has been corrupted"没有字符串数组崩溃,“堆已损坏”
【发布时间】:2021-01-02 05:03:17
【问题描述】:

这个 C 程序读取每行一个字的文件。我想计算文件的唯一单词并将其存储在 totalwords 中,它是通过调用函数的引用传递的。 该程序创建一个字符串数组来存储已经读取的单词。 还有另一个非常简单的函数,它检查一个单词是否已经包含在字符串数组中,称为 isContained(),请参阅本文末尾。 一切似乎都正常,我什至检查了单词是否始终作为唯一单词存储在数组中。但是,当释放数组时,会出现“堆已损坏”错误并且程序崩溃。 对不起,如果这是一个新手问题,但我仔细检查了,我找不到错误在哪里。

提前非常感谢

在 cmets 之后进行的更正(抱歉,我不得不清理原始代码的某些部分以发布示例): @Some 程序员老兄,@ryyker,@kiran biradar,@mlp:我删除了 line 的重复声明并在末尾添加了 free(line)。我还为字符串终止保留了空间。 numrecords 已被删除(它是为澄清而删除的原始代码的一部分)。我使用的是 Visual Studio 2019,在调试模式下没有出现错误,只有 4 个警告。也许我做错了什么。 已删除 sizeof(char)。

谢谢大家。我又检查了一遍。这是由于没有附加终止字符的字符串的另一个 malloc。问题解决了。 非常感谢!

int fileProcessing(char* file_in, int* totalwords) {

    FILE* streamVec;
    char* line = malloc(200);
    int i=0;    
    int numberoflines=1000;
    char** currentList = malloc(numberoflines* sizeof(char*));
    int linelength = 500; //arbitrary value to assure that lines are read completely    

    
    streamVec = fopen(file_in, "r"); 
    if (streamVec == NULL) {
        printf("*** ERROR: Could not open file: %s\n", file_in);
        return 1;
    }

    *totalwords = 0;

    while (fgets(line, linelength, streamVec) != NULL) {      //New line read from the file

                if ( ! isContained(line, currentList, *totalwords)){ //check if the word is already in the list
                        currentList[*totalwords] = malloc(strlen(line) * (sizeof(char)+1));
                        strcpy(currentList[*totalwords], line); 

                        (*totalwords)++;    
                }   
                
    } //End of the read loop

    fclose(streamVec);      

    for (i = 0; i < *totalwords; i++) {
        printf("%i %s\n", i, currentList[i]);       
        free(currentList[i]);       
    }
    free(currentList);
}
int isContained(char* mystring, char** arrayofstring, int arraylength) {

    int i;
    for (i = 0; i < arraylength; i++) {

        if (strcmp(arrayofstring[i], mystring) == 0) {
            return 1;
        }               
    }   
    return 0;
}

【问题讨论】:

  • 为什么要加入malloc(((double)linelength))?在line的初始化中分配的内存会发生什么?
  • 至于您的问题,请记住,在 C 中,字符串实际上称为 null-terminated 字节数组。您还必须记住为空终止符分配空间。
  • currentList[*totalwords] = malloc(strlen(line) * sizeof(char));-->currentList[*totalwords] = malloc(strlen(line) * sizeof(char) + 1); 确保从fgets 删除换行符。
  • while (fgets(line, linelength, streamVec) line 分配了 200 字节,但您将 linelength 定义为 500。这两个参数应该对应。
  • @ryyker 在初始化后为line 分配了一个不幸的新分配。

标签: arrays c string free


【解决方案1】:

您发布的代码可以编译,但在运行时失败。调试器注释并定位到此位置的第一个故障:

...

内存分配似乎是罪魁祸首。

以下是一些建议,以及指向可能对以下建议有所帮助的一两个代码 sn-p 的链接。

问题陈述

  • 将文件中的单词列表(每行一个单词排列)读入单词数组。
  • 数组中不同/唯一单词的计数列表。

任务列表

  • 从原始文件中获取字数。
  • 从原始文件中获取最长单词的长度。
  • 创建存储以包含原始文件中的单词列表。
    使用前两个步骤中收集的信息。)
  • 将原始文件中的单词读入完整的单词数组中。
  • 排序完整的单词数组。 (这是可选的。)
  • 使用您的 isContained() 函数遍历已排序的完整数组以计算唯一/不同的单词列表。

一些建议的帖子供参考:

Get count of words from file。 (这可以适应从文件中获取最长的单词。)
Create storage arrays.
Sort original array. (using qsort())(同样,可选步骤。)

【讨论】:

    【解决方案2】:
    currentList[*totalwords] = malloc(strlen(line) * (sizeof(char)+1));
    

    此行不正确。 应该是:

    currentList[*totalwords] = malloc((strlen(line) + 1) * sizeof(char));
    

    为了为空终止添加额外的字节。

    【讨论】:

    • 谢谢,复制/粘贴原始代码是我的错。我终于摆脱了“sizeof(char)”,只是在最后加了一个+1。
    • 顺便说一句,非常感谢您审阅帖子并试图找出问题的原因。
    • 删除 sizeof(char) 时要小心;在这种情况下它仍然可以工作,但字符串中的字符可能并不总是表示为单个字节。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-12
    • 1970-01-01
    • 2011-06-06
    相关资源
    最近更新 更多