'heap corruption detected after free

Why am I getting an error Heap Corruption Detected after normal block when I trying to free the string? I read a name from a text file into a string (nameS), and after I used this string I try to "free" the memory

    char c;
    int phy = 0;
    int log = 1;
    char *nameS = (char *)malloc(log * sizeof(char));
    int id;

    checkallo(nameS);
    c = fgetc(f);

    while (c != ' ') {
        if (log == phy) {
            log = log * 2;
            nameS = (char *)realloc(nameS, log * sizeof(char));
            checkallo(nameS);
        }
        nameS[phy] = c;
        phy++;
        c = fgetc(f);
    }
    nameS[phy] = '\0';
    phy++;
    
    if (log > phy) {
        nameS = (char *)realloc(nameS, phy * sizeof(char));
        checkallo(nameS);
    }

    id = findInsId(InstTree, nameS);

    free(nameS); // <--- the problem

    return (id);
c


Solution 1:[1]

You must ensure there is enough space for the null terminator. For example if the user enters an one character word, phy and log will be 1 at the beginning of the second iteration, when the test while (c != ' ') stops the loop and nameS[phy] = '\0'; writes beyond the end of the allocated array, causing undefined behavior (corrupting the heap as you observe).

Also note that c should have type int and you should handle EOF.

Note also that stopping on ' ' only is probably incorrect as words might be separated by other white space characters such as TAB or newline.

Here is a modified version:

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>

#define checkallo(p)  do { if (!(p)) perror("allocation error"); } while (0)

int getInsId(FILE *f) {
    int c;
    int phy = 0;
    int log = 0;
    int id;
    char *nameS = malloc(log + 1);
    checkallo(nameS);

    while ((c = fgetc(f)) != EOF && !isspace(c)) {
        if (log == phy) {
            log = log * 2;
            nameS = realloc(nameS, log + 1);
            checkallo(nameS);
        }
        nameS[phy++] = c;
    }
    nameS[phy] = '\0';
    
    if (log > phy) {
        nameS = realloc(nameS, phy + 1);
        checkallo(nameS);
    }

    id = findInsId(InstTree, nameS);

    free(nameS);

    return id;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 chqrlie