Problem with free function in C for pointers

256 views Asked by At

I have two pointers and I want to fill the pointer somme with the values ​​contained in the pointer v.

This is method:

somme[0]=v[0] + v[1];
somme[1]=v[2] + v[3];
somme[2]=v[4] + v[5];

...

The error occurs when it performs the distruggi_vec(somme); function and not distruggi_vec(v);.

do you have any ideas? Thank you for your time.

This is my c code:

#include <stdlib.h>
#include <stdint.h>

extern uint32_t *crea_vec(size_t  n)
{
    uint32_t *p;
    p = malloc(n * sizeof(uint32_t));
    for (size_t i = 0; i < n; ++i)
    {
        p[i] = i;
    }

    return p;
}

uint32_t *somme_2a2(uint32_t *vett, size_t size) 
{
    if (size % 2 != 0) 
    {
        size = size - 1;
    }

    size_t j = 0;
    for (size_t i = 0; i < size; ++i) 
    {
        if (i >= 10) { goto a; }
        j = i * 2;
        vett[i] = vett[j] + vett[j + 1];
    }
    a:
    size = size / 2;
    vett = realloc(vett, size * sizeof(uint32_t));

    return vett;
}

extern void distruggi_vec(uint32_t *p)
{
    free(p);
}

int main(void) 
{
    size_t n = 20;
    uint32_t *v = crea_vec(n);
    uint32_t *somme = somme_2a2(v, n);
    distruggi_vec(v);
    distruggi_vec(somme);

    return 0;
}

when I debug my code it gives me this problem:

3

There are 3 answers

1
KKKKK On BEST ANSWER

Thank you all for your time, this is the final solution of my problem without errors:

Code:

`

#include <stdlib.h>
#include <stdint.h>

extern uint32_t *crea_vec(size_t  n)
{
    uint32_t *p;
    p = malloc(n * sizeof(uint32_t));
    for (size_t i = 0; i < n; ++i)
    {
        p[i] = i;
    }

    return p;
}

uint32_t *somme_2a2(uint32_t *vett, size_t size) 
{
    uint32_t *vett2 = calloc(size/2, sizeof(uint32_t));
    if (size % 2 != 0) 
    {
        size = size - 1;
    }

    size_t j = 0;
    for (size_t i = 0; i < size; ++i) 
    {
        if (i >= 10) { break; }
        j = i * 2;
        vett[i] = vett[j] + vett[j + 1];
        vett2[i] = vett[i];
    }

    return vett2;
}

extern void distruggi_vec(uint32_t *p)
{
    free(p);
}

int main(void) 
{
    size_t n = 20;
    uint32_t *v = crea_vec(n);
    uint32_t *somme = somme_2a2(v, n);
    distruggi_vec(v);
    distruggi_vec(somme);

    return 0;
}

`

1
Sourav Ghosh On

First of all, don't write code like

 vett = realloc(vett, size * sizeof(uint32_t));

in case realloc() fails, you'll lose the original pointer, too.

From the C11, chapter §7.22.3.5

If memory for the new object cannot be allocated, the old object is not deallocated and its value is unchanged.

and

The realloc function returns a pointer to the new object (which may have the same value as a pointer to the old object), or a null pointer if the new object could not be allocated.

Always catch the return value of realloc() in a temp pointer, check it against NULL and if it is valid, you can (optionally) assign it back to the original pointer. Something like (pseudocode)

pointer temp = NULL;
temp = realloc (oldPOinter, size);
if (!temp) 
{
    printf ("Some error message");
    return SOME_ERROR_CODE;
}
oldPOinter = temp;

That said, the problem here, is, in case realloc() is success, the original pointer is no longer to be used. v is passed to somme_2a2() as an argument, and as per C, it's pass by value. Thus, any change made to vett will not reflect back to the caller in v.

However, since the realloc() changes the validity of the memory pointer to by vett, after returning successfully from the somme_2a2() call, in the main(), v is not valid anymore, and you don't need to pass that to free().

Quoting C11, chapter §7.22.3.5

The realloc function deallocates the old object pointed to by ptr and returns a pointer to a new object that has the size specified by size. [...]

Passing vett to free() will cause undefined behavior, because you'll end up attempting to free() a pointer which has already been free()-d [via success of realloc()].

Quoting chapter §7.22.3.3

[...] if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

3
Some programmer dude On

It doesn't matter how many calls to realloc you make, you will still only have one pointer: The one last returned by malloc, calloc or realloc.

After the call to realloc the original pointer becomes invalid, and you should only use the pointer it returns.

That means when you call distruggi_vec with the invalid pointer v you will have undefined behavior.