Search code examples
cmallocfree

I am getting "pointer being freed was not allocated"


I am reading from stdin. Since I do not know the length of what I will read, I have to use malloc.

I am getting a pointer being freed was not allocated

Sometimes, it happens before free(final), sometimes before free(tmp).

I check that both pointers are correctly are non null after creating them and before making free. Can somebody pin point what I am doing wrong ?

total_size = 0;
final = (char *)malloc(sizeof(char) * 1);
if (!final)
{
    printf("Error Allocating Memory for final\n");
    return (NULL);
}
while ((ret = read(0, buf, BUF_SIZE)) > 0)
{
    tmp = (char *)malloc(sizeof(char) * ft_strlen(final));
    if (!tmp)
    {
        printf("Error Allocating Memory for tmp\n");
        return (NULL);
    }
    strcpy(tmp, final);
    if (final)
        free(final);
    buf[ret] = '\0';
    total_size = total_size + ret;
    final = (char *)malloc(sizeof(char) * total_size);
    if (!final)
    {
        printf("Error Allocating Memory for final\n");
        return (NULL);
    }
    final = strcat(tmp, buf);
    if (tmp)
        free(tmp);
}
return (final);

Solution

  • This is a problem for you:

    final = (char *)malloc(sizeof(char) * total_size);
    

    [...]

    final = strcat(tmp, buf);
    

    You are leaking the allocated memory and aliasing *final and *tmp. You can thereafter free one of them, but you must not afterward free the other without first reassigning it to point to a valid dynamically-allocated block.

    Overall, it looks like you are going to a lot of unnecessary trouble with tmp. As far as I can tell, you're just trying to increase the size of the block to which final points, and that's what realloc() is for:

    size_t desired_size = total_size + ret + 1;  // need space for a terminator
    char *tmp = realloc(final, desired_size);
    if (!tmp) {
        perror("Error Allocating More Memory for final");
        // realloc() does not free the pointer on failure; at least GLIBC's doesn't
        free(final);
        return (NULL);
    }
    final = tmp;
    
    buf[ret] = '\0';
    
    // strcat is wasteful if you already know the destination string's length
    strcpy(final + total_size, buf);
    total_size += ret;
    

    The reallocated block may or may not start in the same place as the original, but realloc() takes care of copying the data if necessary.