简体   繁体   中英

asprint memory leak need help understand where leak is coming from and possible fixes

Note: I did call this function and free it main but valgrind still shows error. This code basically takes in a singly linked-list with two data coeff and exp. This is basically converting a polynomial store in a linked list converted to readable string. I looking to have it dynamic allocated.

char *Poly_to_string(const Polynomial *p)
{
    char *x = malloc(1);
    int size;

    while (p != NULL)
    {
        if((p->exp != 0) && (p->exp != 1))
        {
            size = asprintf(&x, "%s%dx^%d + ", x, p->coeff, p->exp);
            if (size == -1)
            {
                exit(-1);
            }
        }   
        else if(p->exp == 1)
        {
            size = asprintf(&x, "%s%dx + ", x, p->coeff);
            if (size == -1)
            {
                exit(-1);
            }
        }
        else if(!p->exp)
        {
            size = asprintf(&x, "%s%d + ", x, p->coeff);
            if (size == -1)
            {
                exit(-1);
            }
        }
        p = p->next;
    }
    x[strlen(x) - 3] = '\0';
    return x;
}

From the Linux asprintf() man page (bolding mine):

DESCRIPTION

The functions asprintf() and vasprintf() are analogs of sprintf(3) and vsprintf(3) , except that they allocate a string large enough to hold the output including the terminating null byte ('\0'), and return a pointer to it via the first argument. This pointer should be passed to free(3) to release the allocated storage when it is no longer needed.

RETURN VALUE

When successful, these functions return the number of bytes printed, just like sprintf(3). If memory allocation wasn't possible, or some other error occurs, these functions will return -1, and the contents of strp are undefined.

This line is wrong:

char *x = malloc(1);

It should just be

char *x;

because if asprintf() works, it will overwrite the contents of x and cause the memory allocated in char *x = malloc(1); to be leaked.

EDIT

The looping also needs to be addressed, as you're trying to grow the string:

char *Poly_to_string(const Polynomial *p)
{
    // start with an empty string that can be free()'d
    // (if you don't have strdup() use malloc() and strcpy())
    char *x = strdup("");
    int size;

    while (p != NULL)
    {
        // save the old malloc()'d value so it can be free()'d
        char *oldValue = x;

        if((p->exp != 0) && (p->exp != 1))
        {
            size = asprintf(&x, "%s%dx^%d + ", x, p->coeff, p->exp);
            if (size == -1)
            {
                exit(-1);
            }
        }   
        else if(p->exp == 1)
        {
            size = asprintf(&x, "%s%dx + ", x, p->coeff);
            if (size == -1)
            {
                exit(-1);
            }
        }
        else if(!p->exp)
        {
            size = asprintf(&x, "%s%d + ", x, p->coeff);
            if (size == -1)
            {
                exit(-1);
            }
        }

        // free() the old value
        free(oldValue);
        p = p->next;
    }
    x[strlen(x) - 3] = '\0';
    return x;
}

There are other ways to do this without the initial char *x = strdup(""); but the code then becomes a lot more complex.

You're not deallocating variable x

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