Carpo Crates
Carpo Crates

Reputation: 78

free of array of strings crashes with "A heap has been corrupted"

This C program reads a file with a word per line. I'd like to count the unique words of the file and store it in totalwords, which is passed by reference from the caller function. The program creates an array of strings to store the words that haven been read already. There is another function, quite simple, that checks if a word is already contained in the array of strings, called isContained(), please see at the end of this post. All seems to work OK, and I even checked that the words are consistently stored in the array as unique words. However, when freeing the array the error ""A heap has been corrupted" raises and the program crashes. Sorry if this a newbie question, but I double checked and I cannot find where the error is.

Thanks a lot in advance

Corrections made after comments (sorry, I had to clean up some parts of the original code for posting the example): @Some programmer dude, @ryyker, @kiran biradar, @mlp: I deleted the duplicated declaration of line and added the free(line) at the end. I also reserved space for the string termination. numrecords has been deleted (it was part of the original code deleted for clarification).I'm using Visual Studio 2019, no error arises in debug mode, just 4 warnings. Maybe I'm doing something wrong. Deleted sizeof(char).

Thank you all. I checked again. It was due to another malloc for a string without the additional termination char. Problem solved. Thank you very much!

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;
}

Upvotes: 1

Views: 127

Answers (2)

JRT
JRT

Reputation: 238

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

This line is incorrect. It should be:

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

in order to add the extra byte for the null-termination.

Upvotes: 1

ryyker
ryyker

Reputation: 23218

The code you posted compiles, but fails at run-time. The debugger annotated and located the first failure to this location:

enter image description here ...
enter image description here

memory allocation seems to be the culprit.

Following are a few suggestions, and links to a code snippet or two that may help with the following suggestions.

Problem statement:

  • Read list of words from file (arranged with one word per line) into array of words.
  • count list of distinct/unique words from array.

List of tasks:

  • obtain count of words from original file.
  • obtain length of longest word from original file.
  • create storage to contain list of words from original file.
    (using information gathered in previous two steps.)
  • read words from original file into full array of words.
  • sort full array of words. (this is optional.)
  • loop through sorted full array to count unique/distinct list of words using your isContained() function.

Some suggested posts for reference:

Get count of words from file. (This can be adapted to get longest word from file.)
Create storage arrays.
Sort original array. (using qsort()) (Again, optional step.)

Upvotes: 3

Related Questions