简体   繁体   中英

C Free While Reading Text File

I am working on a project and in this program I want to read given txt file line by line. Separate each line by space and get an array of words in that line. After that operation I want to free all mallocs but when I try to free it gives error.

    FILE * filePointer;
    char * lineFromText = NULL;
    size_t lengthOfLine = 0;
    ssize_t lastIndexOfText;
    filePointer = fopen("/home/ogr/b21xxxxxxx/input5.txt", "r");
    if (filePointer == NULL)
        exit(EXIT_FAILURE);
    char **array=malloc(sizeof(char*)*10);
    int i;
    for (i=0; i<10; i++) {
        array[i] = malloc(10 * sizeof(char*));
    }
    while ((lastIndexOfText = getline(&lineFromText, &lengthOfLine, filePointer)) != -1)
    {
        lineFromText[lastIndexOfText-2]='\0';
        char * pch = malloc(10 * sizeof(char));
        strcpy(pch,strtok (lineFromText," "));
        while (pch != NULL)
        {
            int loop;
            array[0]=pch;
            if(array[0]==NULL) {
                printf("No test to search.\n");
                exit(0);
            }
            for(loop=1;loop<10;loop++) {
                array[loop]=strtok(NULL," ");
                if(array[loop]==NULL)
                    break;
            }
            for(loop=0;loop<10;loop++) {
                if(array[loop]==NULL)
                    break;
                printf("Item #%d is %s\n",loop,array[loop]);
            }
            pch = strtok (NULL, " ");
        }
    }
    fclose(filePointer);
    int j;
    for (j = 0; j < 10 ; j++) {
        free(array[j]);
    }

You can see text file from here : input5.txt

The reason of why you getting an error on free is that you are corrupting pointers originally returned by malloc. But the real reason is somewhere deeper.

Let's deal with that free error first. Here is how you allocating memory:

for (i=0; i<10; i++) {
    array[i] = malloc(10 * sizeof(char*));
}

Here each of 10 array entries is assigned with pointer returned by malloc call. Each of that pointers point on 40 or 80 byte memory chunk ( sizeof(char*) gives 4 on x86 and 8 on x64) allocated.

To free up that memory the one should pass the pointers returned by malloc to the free function:

int j;
for (j = 0; j < 10 ; j++) {
    free(array[j]);
}

But it doesn't work in your case because of the following code:

char * pch = malloc(10 * sizeof(char));
strcpy(pch,strtok (lineFromText," "));
while (pch != NULL)
{
    int loop;
    array[0]=pch;
    ...
    for(loop=1;loop<10;loop++) {
        array[loop]=strtok(NULL," ");
        if(array[loop]==NULL)
            break;
    }

Here you overwriting the addresses originally returned by malloc and stored in array with the ones returned by strtok . So all of the allocated memory is being leak, and you getting an error cause when it comes to free your array[0] contains pch address (first word in the last line) and array[1] containg pch plus second word offset address which is already freed on first cycle iteration.

The real thing here is that you really don't need any extra memory allocations beside those that are done by getline . Firstly you can declare a statically allocated array of pointers:

char *array[10];

instead of:

char **array=malloc(sizeof(char*)*10);
int i;
for (i=0; i<10; i++) {
    array[i] = malloc(10 * sizeof(char*));
}

Then initialize pch like this:

char *pch = strtok (lineFromText," ");

instead of:

char * pch = malloc(10 * sizeof(char));
strcpy(pch,strtok (lineFromText," "));

After processing is done, it only remains to free up lineFromText buffer, because it gets allocated by getline :

free(lineFromText)

instead of:

int j;
for (j = 0; j < 10 ; j++) {
    free(array[j]);
}

Hope this help. Good luck.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM