Search code examples
cmemory-leaksmemory-managementdynamic-memory-allocation

realloc after free problem ("realloc: invalid next size")


I've got a strange problem with realloc, here's my code (relevant parts only, too big to post the full code here):

char * print_bar(struct bar *ptr) {
    char *buf = NULL;
    char *buftmp = NULL;
    size_t size = 60;
    int count = 0;

    if (ptr) {
        while (count == 0 || count+4 >= size) {
            buftmp = (char *) realloc((void *) buf, size * sizeof (char));
            if (buftmp == NULL) {
                if (buf != NULL) free(buf);
                exit(EXIT_FAILURE);
            }
            buf = buftmp;

            count = snprintf(buf, size, "%04d-%02d-%02d\t%02d:%02d:00\t%d\t%.2f\t%.2f\t%.2f\t%.2f\t%d",
                    ptr->year,
                    ptr->month,
                    ptr->day,
                    ptr->hour,
                    ptr->minute,
                    ptr->timeframe,
                    ptr->open,
                    ptr->high,
                    ptr->low,
                    ptr->close,
                    ptr->volume
                    );

            size += 4;
        }
    }

    return buf;
}

char * print_historico(short timeframe) {
    struct barlist *tmp = get_barlist(timeframe);
    struct bar *ptr;
    char * result = NULL;
    char * resulttmp = NULL;
    char * buf;
    int len;

    if (tmp) {
        ptr = tmp->first;
        while (ptr) {
            buf = print_bar(ptr);
            len = (result != NULL) ? strlen(result)+strlen(buf)+1 : strlen(buf)+1;
            resulttmp = (char *)realloc((void *)result, len);
            if (resulttmp == NULL)
            {
                if (result != NULL) free(result);
                exit (EXIT_FAILURE);
            }
            result = resulttmp;
            strncat(result, buf, strlen(buf));

            free(buf);
            ptr = ptr->next;
        }
    }

    return result;
}

In my main function i've got the following loop:

for (i = 1; i <= 27; i++) {
    historico = print_historico(i);
    if (historico != NULL)
    {
        puts(historico);
        free(historico);
    }
}

If i compile and run it fails with "realloc(): invalid next size: 0x0000000001704f60". If i run with the debugger i see it finishes the first iteration of the main loop ok, freeing the 'historico' variable. When it executes "print_historico" with i=2 it fails on the second iteration of the "while(ptr)" loop.

I can't find a reason, any clue? I've also tried to make a small program to isolate the problem, but i wasn't able.


Solution

  • strncat(result, buf, strlen(buf));
    

    This is a problem. (It might be the cause of the problem you are reporting having.)

    When the first realloc occurs, the result is not initialized. You really need to put a '\0' in the first char position for the strncat to work (reliably).

    resulttmp = (char *)realloc((void *)result, len);
            if (resulttmp == NULL)
            {
                if (result != NULL) free(result);
                exit (EXIT_FAILURE);
            }
    if(result == NULL) *resulttmp = '\0' // YOU NEED THIS!! First time initialization.