Realloc不起作用(遵循CS50讲座5中的说明)

发布于 2025-02-06 12:48:18 字数 1189 浏览 2 评论 0原文

我将向list array添加新值4list数组中的原始值是1,2,3
但是,当我运行以下代码时,我没有得到1,2,3,4,而是几个随机数。
每次运行时,我都会获得不同的输出。
有人可以帮我找出这里出了什么问题吗?
多谢。

#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; //最后记得加上这个
}

输出就是这样:

1609039888
25764
2043
4

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

热情消退 2025-02-13 12:48:18

尝试此代码

#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; //最后记得加上这个

}

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; //最后记得加上这个

}

迷荒 2025-02-13 12:48:18

关于动态内存管理的工作方式实际上是一个基本的误解...

首先,如果分配失败(malloc返回零指针),那么无论如何都没有什么可免费的,所以您简直不需要(即使是合法的 - 然后有效地是一个毫无疑问...)。

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

然后realloc 已经为您替换 !您可以想象它可以这样起作用:

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;
}

请注意,如果重新分配失败,旧数据如何保持完整,但会因成功而删除!

因此,正确使用realloc看起来如下:

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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文