1

why the below code gives me error of "double free or corruption"... when i compile and run with gcc [(Debian 4.4.4-8) 4.4.5 20100728 (prerelease)]. Thanks in advance!

#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;
}
jkl
  • 75
  • 2
  • 6
  • if you have 2 questions to make, start 2 posts. Do not reuse one post to make another question. **Welcome to SO, have fun!** – pmg Sep 24 '10 at 16:03

4 Answers4

1

Because the storage pointed to by 'a' and 'one.index1' are the same (assignment before the first printf). Thus you have a double free.

Darron
  • 21,309
  • 5
  • 49
  • 53
1
one.index1=a;
...
free(a);
...
free(one.index1);
...

Ergo, the double free.

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

When you pass the a pointer to this function, its value(which is infact an address), gets copied into b, another local int pointer. Now, when you realloc space for 5 ints, it changes the space allocation for a infact. So your space gets reduced from 10 to 5 ints.

As requested by OP, to get the same data & separate memory pointers, space must be allocated afresh for the new pointer, as a pointer is after all, just a variable, holding an address. If you allocate two separate blocks, you would get two separate addresses, which can be freed individually.

  • How can I get a copy of "a" stored in "one.index1" not the pointer? – jkl Sep 24 '10 at 15:49
  • a has an address. This address gets copied to one.index1. So, now both have the same address. If you perform a free() on one, the space allocated from that address onwards is freed. If you try to free the same space again, you will encounter an error. –  Sep 24 '10 at 15:54
  • So is there anyway to say it to clone "a", and assign that clone to "one.index1"? So that both "a" and "one.index1" will have the same data, but separate memory pointer. – jkl Sep 24 '10 at 15:56
  • You must allocate space & copy the data over to new space. So, then you get 2 blocks of memory, which can each be freed. What's more, now you have got your "separate" pointers, as a & one.index1 have different addresses. –  Sep 24 '10 at 16:05
0

You are passing to doo a pointer. You modify the pointer itself, but your main function does not get the new address.

Benoit
  • 76,634
  • 23
  • 210
  • 236
  • How can I get a copy of "a" stored in "one.index1" not the pointer? – jkl Sep 24 '10 at 15:49
  • @pmg, OP is shrinking allocated memory space. Why would that cause any relocation or change of address? –  Sep 24 '10 at 16:00
  • Guessing how it works internally is not a reason to produce bad code! Implementation could change. – Benoit Sep 24 '10 at 16:02
  • I have to hurry now, can't check the Standard ... I'm pretty sure it allows realloc() to move the objects under any conditions – pmg Sep 24 '10 at 16:09
0

That happens because you make one.index1 and a point to the same memory location.

To test this add the following to your code:

 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.

You'll notice that both pointers will print the same memory addresses. So after free(a); is executed, performing free(one.index1); is redundant, and trying to free a resource that is not allocated anymore is what is causes the problem.

karlphillip
  • 92,053
  • 36
  • 243
  • 426
  • You can't print an address with the "%x" format specifier and expect a reasonable output on all systems. Use "%p" format specifier and cast the address to `void*` *(and don't expect a reasonable output on all systems)*. – pmg Sep 24 '10 at 16:01
  • 1
    @pmg Thank you. You can print it as you like. – karlphillip Sep 24 '10 at 16:08