***See Latest Update***
-----------------------

Given the following function, note the location of the call `free(tmp)`:

```
int *power_arr(int *n, int nlength, int exp, int *res_length)
{
    int *tmp, *rt, *bufp;
    int bufp_length, i, dbg_i;

    rt = malloc(sizeof(int) * 1000);
    bufp = malloc(sizeof(int) * 1000);

    if (!rt || !bufp)
    {
        return NULL;
    }

    copy(rt, n, nlength);
    copy(bufp, n, nlength);

    *res_length = bufp_length = nlength;

    while (--exp > 0)
    {
        for (i = *n - 1; i > 0; i--)
        {
            tmp = sum(rt, *res_length, bufp, bufp_length, res_length);

            if (!tmp)
            {
                exit(-1);
            }

            copy(rt, tmp, *res_length);
           //free(tmp); // produces undefined output?
        }

        copy(bufp, rt, *res_length);
        bufp_length = *res_length;
    }

    free(tmp);

    free(bufp);

    return rt;
}

```

The result of the following main function:

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

int main(void)
{
    int b[] = { 3 };
    int r, i;
    int *rlength, *res;

    r = 0;

    rlength = &r;

    res = power_arr(b, 1, 3, rlength);

    printf("Length = %d\n", *rlength);

    for (i = 0; i < *rlength; i++)
    {   
        printf("i=");
        printf("%d\n", res[i]);
    }

    printf("\n");

    exit(0);
}

```

Is:

```
Length = 2
i=2
i=7

```

My understanding of the first scenario, is that there is a memory leak for every subsequent `tmp = sum(rt, *res_length, bufp, bufp_length, res_length);` call. Which point, I decided to move the call to `free(tmp)` inside the *for* loop. Once moved, I had noticed that the output had changed, as follows:

```
Length = 4
i=1018670
i=4
i=2
i=7

```

I can see that the answer begins at i[3]. Why does the movement of the `free(tmp)` call, cause this effect?

My understanding is that `tmp` becomes a *dangling pointer* after the `free()` call. Then, it is re-assigned a value returned by the function `sum()` - which was retrieved by a call to `malloc()`. Which point, a memory leak would occur by placing the call to `free()` in its original location. As the value of `tmp` will change, only *freeing* the last pointer assigned to it.

---

Edit:
-----

Below is the code for the supporting functions.

```
int *pad(int *n, int nlength, int new_length, enum SIDE side)
{
    int i, j;
    int *padded;

    if (nlength < 1 || new_length <= nlength)
    {
        return NULL;
    }

    padded = calloc(new_length, sizeof(int));

    if (!padded)
    {
        return NULL;
    }

    if (side == LOW)
    {
        j = new_length - 1;

        for (i = (nlength - 1); i >= 0; i--)
        {
            padded[j--] = n[i];
        }
    }
    else
    {
        j = 0;

        for (i = 0; i < nlength; i++)
        {
            padded[j++] = n[i];
        }
    }

    return padded;
}

int *trim(int *n, int nlength, int *res_length)
{
    int i, j;
    int *res;

    for (i = 0; i < nlength; i++)
    {
        if (n[i] > 0)
        {
            break;
        }
    }

    *res_length = (nlength - i);

    res = malloc(sizeof(int) * (*res_length));

    if (!res)
    {
        return NULL;
    }

    j = 0;

    while (i < nlength)
    {
        res[j++] = n[i++];
    }

    return res;
}

int *sum(int *n, int nlength, int *m, int mlength, int *sum_length)
{
    int i, tmp, carry;
    int *result, *trimmed, *op1, *op2;
    enum SIDE side = LOW;

    if (nlength == mlength)
    {
        op1 = n;
        op2 = m;
    }
    else if (nlength > mlength)
    {
        op1 = n;
        op2 = pad(m, mlength, nlength, side);
    }
    else
    {
        op1 = m;
        op2 = pad(n, nlength, mlength, side);
    }

    result = malloc(sizeof(int) * (MAX(nlength, mlength) + 1));

    if (!op1 || !op2 || !result)
    {
        return NULL;
    }

    carry = 0;

    for (i = (MAX(nlength, mlength)) - 1; i >= 0; i--)
    {
        tmp = op1[i] + op2[i] + carry;

        if (carry > 0)
        {
            carry = 0;
        }

        if (tmp >= 10)
        {
            carry = tmp / 10;
            tmp = tmp % 10;
        }

        result[i + 1] = tmp;
    }

    if (carry > 0)
    {
        result[0] = carry--;
    }

    *sum_length = (MAX(nlength, mlength)) + 1;

    trimmed = trim(result, *sum_length, sum_length);

    free(result);

    if (!trimmed)
    {
        return NULL;
    }

    return trimmed;
}

void copy(int *to, int *from, int length)
{
    int i;

    for (i = 0; i < length; i++)
    {
        to[i] = from[i];
    }
}

```

---

Update:
-------

After implementing the changes suggested in the first post, a *double free* error has begun occurring, to debug, I added the following print statements to the `power_arr()`. The output following shows that `tmp` is being assigned the same value from `sum()`, as it received on the initial call. Why?

Updated code showing debug `printf` statements:

```
    for (i = *n - 1; i > 0; i--)
    {
        tmp = sum(rt, *res_length, bufp, bufp_length, res_length);

        printf("first tmp = %d\n", tmp);

        if (!tmp)
        {
            printf("tmp was null\n");
            exit(-1);
        }

        copy(rt, tmp, *res_length);

        printf("second tmp = %d\n", tmp);\

        if (tmp != NULL)
        {
            printf("freeing tmp\n");
            free(tmp);
            tmp = NULL;
        }

        printf("tmp = %d\n", tmp);
    }

```

The output:

```
first tmp = 11227072
second tmp = 11227072
freeing tmp
tmp = 0
first tmp = 11227072 <-- Why has the pointer value not changed?
second tmp = 11227072
freeing tmp <-- Double free now occuring.
*** Error in `./a.out': double free or corruption (fasttop):        0x0000000000ab4fc0 ***
Aborted

```

---

Update:
-------

I believe I have tracked the bug down to the `trim()` function. I have posted the function with a *loop* to execute it 10 times in succession. As you can see in the output, `trim()` - which calls `malloc()`, returns the same pointer value on subsequent calls. Yet, each successive call to free does not trigger a *double free* error. Why is this the case?

```
int main()
{
    int i, j, length;
    int n[] = { 4, 5, 6 };
    int m[] = { 0, 3, 5 };
    int *num;
    int *trimmed, *trimmed_length;

    trimmed_length = &length;

    for (i = 0; i < 10; i++)
    {
        num = (i % 2 == 0) ? n : m;

        trimmed = trim(num, 3, trimmed_length);

        if (!trimmed)
        {
            printf("trimmed was null\n");
            exit(-1);
        }

        for (j = 0; j < *trimmed_length; j++)
        {
            printf("%d", trimmed[j]);
        }   

        printf("\n");

        free(trimmed); 
    }

    exit(0);
} 

int *trim(int *n, int nlength, int *res_length)
{
    int i, j;
    int *res;

    for (i = 0; i < nlength; i++)
    {
        if (n[i] > 0)
        {
            break;
        }
    }

    *res_length = (nlength - i);

    res = malloc(sizeof(int) * (*res_length));

    if (!res)
    {
        return NULL;
    }

    j = 0;

    while (i < nlength)
    {
        res[j++] = n[i++];
    }

    printf("Returned pointer from trim() %d\n", res);

    return res;
}

```

Output:

```
Returned pointer from trim() 39534608
456
Returned pointer from trim() 39534608
35
Returned pointer from trim() 39534608
456
Returned pointer from trim() 39534608
35
Returned pointer from trim() 39534608
456
Returned pointer from trim() 39534608
35
Returned pointer from trim() 39534608
456
Returned pointer from trim() 39534608
35
Returned pointer from trim() 39534608
456
Returned pointer from trim() 39534608
35

```

This also appears to be the behavior in my original question - which triggers a *double free* error. Why is the *double free* error not encountered in this particular situation?