#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上找到了答案:
原文地址: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呢?