2010-09-24 50 views
1

为什么下面的代码给我错误的“双免费或腐败”......当我编译和运行gcc [(Debian 4.4.4-8) 4.4.5 20100728(预售)]。提前致谢!ansi c struct {with dynamic array}分配给数组,这是realloc

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

typedef struct 
{ 
int *index1; 
} data; 

void doo(int *); 

int main(int argc, char *argv[]) 
{ 
int *a = (int *) malloc(10*sizeof(int)); 
int i; 

for(i=0; i<10; i++) 
{ 
    a[i] = 2*i; 
} 

doo(a); 

data one; 
one.index1 = a; 

printf("%d\n", one.index1[4]); 

free(a); 

printf("%d\n", one.index1[4]); 

free(one.index1); 
return 0; 
} 

void doo(int *b) 
{ 
b = (int *) realloc(b, 5*sizeof(int)); 
return; 
} 
+0

这是家庭作业btw? – 2010-09-24 15:55:33

+0

如果你有2个问题,请发起2帖子。不要重复使用一个帖子来提出另一个问题。 **欢迎来到SO,玩得开心!** – pmg 2010-09-24 16:03:07

回答

1
one.index1=a; 
... 
free(a); 
... 
free(one.index1); 
... 

埃尔戈双免费。

void doo(int *b) 
{ 
b = (int *) realloc(b, 5*sizeof(int)); 
return; 
} 

在您通过一个指向这个函数,其值(这是逸岸的地址),被复制到b中,另一个本地INT指针。 现在,当您为5个整数重新分配空间时,它将更改一个infact的空间分配。所以你的空间从10减少到5。

根据OP的要求,为了得到相同的数据&单独的内存指针,空间必须重新分配给新指针,因为指针毕竟只是一个变量,持有一个地址。如果你分配两个独立的块,你会得到两个单独的地址,可以单独释放。

+0

如何获取存储在“one.index1”中的“a”副本“不是指针? – jkl 2010-09-24 15:49:52

+0

a有一个地址。该地址被复制到one.index1。所以,现在都有相同的地址。如果您在一个上执行free(),则从该地址开始分配的空间将被释放。如果您尝试再次释放相同的空间,则会遇到错误。 – 2010-09-24 15:54:21

+0

无论如何说它克隆“a”,并将该克隆分配给“one.index1”?因此,“a”和“one.index1”将具有相同的数据,但分开的存储器指针。 – jkl 2010-09-24 15:56:42

1

因为'a'和'one.index1'指向的存储是相同的(在第一个printf之前的赋值)。因此你有一个双倍免费。

+0

如何获取存储在“one.index1”中而不是指针的“a”副本? – jkl 2010-09-24 15:50:46

0

你正在传递一个指针。你修改指针本身,但你的主函数不会得到新的地址。

+0

不是“双免费”的原因,但值得更正 – pmg 2010-09-24 15:48:40

+0

如何获取存储在“one.index1”中的“a”而不是指针的副本? – jkl 2010-09-24 15:49:14

+0

@pmg,OP正在收缩分配的内存空间。为什么会导致搬迁或更改地址? – 2010-09-24 16:00:06

0

发生这种情况是因为您使one.index1a指向相同的内存位置。

为了测试这种添加以下代码:

one.index1 = a; // from now on, both variables point to the same address 

printf("-> 0x%x\n", one.index1); 
printf("-> 0x%x\n", a); 

printf("%d\n", one.index1[4]); 

free(a); // release the resource pointed by a 

// You should not try to print the data of one.index1[4] since 
// that piece of memory doesn't exist no more. 
printf("%d\n", one.index1[4]); 

free(one.index1); // Problem: trying to free the same memory resource TWICE. 

你会发现,这两个指针将打印相同的内存地址。因此在free(a);执行后,执行free(one.index1);是多余的,并且尝试释放未再分配的资源是导致问题的原因。

+0

您无法使用“%x”格式说明符打印地址,并希望在所有系统上输出合理的结果。使用“%p”格式说明符并将地址转换为'void *'*(并且不要期望所有系统都有合理的输出)*。 – pmg 2010-09-24 16:01:50

+1

@pmg谢谢。你可以打印它,只要你喜欢。 – karlphillip 2010-09-24 16:08:10