Home > OS >  Realloc does not work (following the instruction in cs50 lecture 5)
Realloc does not work (following the instruction in cs50 lecture 5)

Time:06-11

I'm going to add a new value 4 to the list array.
The original values in list array are 1,2,3.
But when i run the following code, i didn't get 1,2,3,4 but several random numbers.
Each time I run I get different output.
Can someone help me figure out what's going wrong here?
Thanks a lot.

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

int main(void){
    int *list = malloc(3 * sizeof(int));

    //如果直接写int list[3] 就没有办法修改大小了
    if (list == NULL)
    {
        free(list);
        return 1;
    }

    list[0] = 1;
    list[1] = 2;
    list[2] = 3;

    //resize the old array to be of size 4
    //用realloc指定下old array,无需再做copy的工作
    int *tmp = realloc(list, 4 * sizeof(int));

    if (list == NULL)
    {
        free(list); 
        //a safety check, free the original list
        return 1;
    }

    tmp[3] = 4;

    //free old array
    free(list); //这里就可以free之前的list了

    //remember new array
    list = tmp;
    //所以不需要在free(tmp), free(list)相当于free(tmp)

    //print new array
    for (int i = 0; i < 4; i  )
    {
        printf("%i\n", list[i]);
    }

    //free new array
    free(list);
    return 0; //最后记得加上这个
}

the output is like this:

1609039888
25764
2043
4

CodePudding user response:

There's a fundamental misunderstanding on how dynamic memory management actually works...

At first, if an allocation fails (malloc returning a null pointer), then there's nothing to free anyway, so you simply don't need to (even though it's legal – then effectively a no-op...).

int* list = malloc(...);
if(!list) // shorter for list == NULL
{
    return -1;
}

Then realloc replaces the old array for you already! You can imagine it to work like this:

void* realloc(void* oldData, size_t desired)
{
    // retain currently allocated memory size from pointer
    // that's OS/compiler specific knowledge, usually stored somewhere
    // in front of the memory the pointer points to, but not (legally)
    // accessible by you...
    size_t old = ...;

    if(desired <= old)
    {
        return oldData;
    }
    void* newData = malloc(desired);
    if(newData)
    {
        memcpy(newData, oldData, oldSize);
        free(oldData); // !!!
    }
    return newData;
}

Note how the old data remains intact if re-allocation fails, but gets deleted on success!

Correct usage of realloc thus looks as follows:

int* tmp = realloc(list, desiredSize);
if(!tmp)
{
    // appropriate error handling
    // usually you cannot meaningfully go on anyway, so let's just exit
    
    // but HERE list still points to valid memory, so clean up first:
    free(list);

    return -1;
}

// we can safely use the temporary as the list now; note that the old
// memory already HAS been deleted!
list = tmp;

// and now we simply use it:
list[3] = 4;
free(list); // when done

CodePudding user response:

try this code

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

int main(void){
int *list = malloc(3 * sizeof(int));

//如果直接写int list[3] 就没有办法修改大小了
if (list == NULL)
{
    free(list);
    return 1;
}

list[0] = 1;
list[1] = 2;
list[2] = 3;

//resize the old array to be of size 4
//用realloc指定下old array,无需再做copy的工作
int *tmp = realloc(list, 4 * sizeof(int));

if (list == NULL)
{
    free(list); 
    //a safety check, free the original list
    return 1;
}

tmp[3] = 4;

//free old array
//free(list); //这里就可以free之前的list了 // this free the last memory location which empty the array. 

//remember new array
list = tmp;
//所以不需要在free(tmp), free(list)相当于free(tmp)

//print new array
for (int i = 0; i < 4; i  )
{
    printf("%i\n", list[i]);
}

//free new array
free(list);
return 0; //最后记得加上这个

}

  • Related