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

int main()
{
    int size, i, temp;
    char choice[10];
    printf("size: ");
    scanf("%d", &size);
    int* vec = (int*)malloc(sizeof(int) * size);
    int* useless = (int*)malloc(sizeof(int) * size);
    printf("elements: ");
    for (i = 0; i < size; ++i)
    {
        scanf("%d", &vec[i]);
    }
    while (1)
    {
        printf("\\ndo you want to add element?(Y/N): ");
        scanf("%10s", choice);
        if (choice[0] == 'N')
            break;
        printf("element: ");
        scanf("%d", &temp);
        int* ext_vec = (int*)realloc(vec, sizeof(int)*(++size));
        ext_vec[size-1] = temp;
        for (i = 0; i < size; ++i)
        {
            printf("%d ", ext_vec[i]);
        }

    }
    
    return 0;
}

这段代码的本意是使用realloc函数实现一个可变长度的数组,(看《C陷阱与缺陷》介绍realloc时有感而发想写的)但是在测试时发生了一下报错:

检测到doublefree

yiqiu@LAPTOP-I2IQS5DP ~/B/C/h/chapter7> ./a.out
size: 5
elements: 1 2 3 4 5
do you want to add element?(Y/N): Y
element: 6
1 2 3 4 5 6 
do you want to add element?(Y/N): Y
element: 7
1 2 3 4 5 6 7 
do you want to add element?(Y/N): Y
element: 8  
free(): double free detected in tcache 2
fish: './a.out' terminated by signal SIGABRT (Abort)

百思不得其解

最后在Google上找到了答案:

Untitled

原文地址:https://blog.csdn.net/vevenlcf/article/details/47036127

于是为了验证这个答案,我在代码中添加了两行打印地址的代码(红色高亮)

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

int main()
{
    int size, i, temp;
    char choice[10];
    printf("size: ");
    scanf("%d", &size);
    int* vec = (int*)malloc(sizeof(int) * size);
    printf("%p\\n", vec); #打印vec的初始地址
    int* useless = (int*)malloc(sizeof(int) * size);
    printf("elements: ");
    for (i = 0; i < size; ++i)
    {
        scanf("%d", &vec[i]);
    }
    while (1)
    {
        printf("\\ndo you want to add element?(Y/N): ");
        scanf("%10s", choice);
        if (choice[0] == 'N')
            break;
        printf("element: ");
        scanf("%d", &temp);
        int* ext_vec = (int*)realloc(vec, sizeof(int)*(++size));
        printf("%p\\n", ext_vec); #在这里打印ext_vec的地址
        ext_vec[size-1] = temp;
    
        for (i = 0; i < size; ++i)
        {
            printf("%d ", ext_vec[i]);
        }

    }
    
    return 0;
}
yiqiu@LAPTOP-I2IQS5DP ~/B/C/h/chapter7> ./a.out
size: 5
0x562e070abac0
elements: 1 2 3 4 5
do you want to add element?(Y/N): Y
element: 6
0x562e070abac0
1 2 3 4 5 6 
do you want to add element?(Y/N): Y
element: 7
0x562e070abb00
1 2 3 4 5 6 7 
do you want to add element?(Y/N): Y
element: 8
free(): double free detected in tcache 2
fish: './a.out' terminated by signal SIGABRT (Abort)

果然在添加7这个元素后,realloc的地址发生了变化

所以此时其实vec这个地址的内存其实已经被free了,再次添加8这个元素时,传入vec的地址给realloc函数就会引发double free了

由此,修改代码如下(红色高亮部分)

每次realloc后都将ext_vec的值赋给vec,这样vec也就跟着改变了

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

int main()
{
    int size, i, temp;
    char choice[10];
    printf("size: ");
    scanf("%d", &size);
    int* vec = (int*)malloc(sizeof(int) * size);
    printf("%p\\n", vec);
    int* useless = (int*)malloc(sizeof(int) * size);
    printf("elements: ");
    for (i = 0; i < size; ++i)
    {
        scanf("%d", &vec[i]);
    }
    while (1)
    {
        printf("\\ndo you want to add element?(Y/N): ");
        scanf("%10s", choice);
        if (choice[0] == 'N')
            break;
        printf("element: ");
        scanf("%d", &temp);
        int* ext_vec = (int*)realloc(vec, sizeof(int)*(++size));
        printf("%p\\n", ext_vec);
        ext_vec[size-1] = temp;
        vec = ext_vec;
        for (i = 0; i < size; ++i)
        {
            printf("%d ", ext_vec[i]);
        }

    }
    
    return 0;
}
yiqiu@LAPTOP-I2IQS5DP ~/B/C/h/chapter7> ./a.out
size: 5
0x5641d65feac0
elements: 1 2 3 4 5
do you want to add element?(Y/N): Y
element: 6
0x5641d65feac0
1 2 3 4 5 6 
do you want to add element?(Y/N): Y
element: 7
0x5641d65feb00
1 2 3 4 5 6 7 
do you want to add element?(Y/N): Y
element: 8
0x5641d65feb00
1 2 3 4 5 6 7 8 
do you want to add element?(Y/N): Y
element: 9
0x5641d65feb00
1 2 3 4 5 6 7 8 9 
do you want to add element?(Y/N): Y
element: 10
0x5641d65feb00
1 2 3 4 5 6 7 8 9 10 
do you want to add element?(Y/N): Y
element: 11
0x5641d65feb00
1 2 3 4 5 6 7 8 9 10 11 
do you want to add element?(Y/N): Y
element: 12
0x5641d65feb00
1 2 3 4 5 6 7 8 9 10 11 12 
do you want to add element?(Y/N): N

最后:为什么realloc的返回值会有可能不等于vec呢?