0

我是编码初学者,我的代码有问题。请指教。

输入:-

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

int main (void)
{
    int *list = malloc(3 * sizeof(int));
    if (list == NULL)
    {
        return 1;
    }

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

   for (int i = 0; i < 3; i++)
   {
       printf("%i\n", list[i]);
   }

    int *tmp = realloc(list, 4 * sizeof(int));
    if (tmp == NULL)
    {
        free(list);
        return 1;
    }

    free(list);

    tmp[3] = 4;

    list = tmp;

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

    free(tmp);
}

输出:-

1
2
3
1628405245
5
-136327152
4

我有一个问题,free(list);如果我删除它,那么代码似乎工作正常,

但如果我这样做(这是在 CS50 的讲座中完成的)

tmp[3] = 4;

free(list);

然后错误来了

1
2
3
1508201014
5
1428381712
21918
free(): double free detected in tcache 2
zsh: abort      ./list1

请问这是为什么?

4

1 回答 1

1

根据 C 标准(7.22.3.5 realloc 函数)

2 realloc 函数释放 ptr 指向的旧对象,并返回一个指向具有 size 指定大小的新对象的指针。

  1. ...如果无法为新对象分配内存,则不会释放旧对象并且其值不变。

因此,此代码段中的最后一次免费调用

int *tmp = realloc(list, 4 * sizeof(int));
if (tmp == NULL)
{
    free(list);
    return 1;
}

free(list);

调用未定义的行为,因为指针列表指向的旧对象的内存已在此成功调用 realloc 中释放

int *tmp = realloc(list, 4 * sizeof(int));

您需要删除此代码段中的最后一次免费调用。

同样在此代码段中

tmp[3] = 4;

free(list);

出于同样的原因, free 的调用会调用未定义的行为。

注意 realloc 可以返回重新分配内存的相同地址或重新分配内存的新地址。这会影响未定义行为的结果。

于 2022-01-10T11:22:34.620 回答