0

I have declared double pointer in main and allocate memory like this

char  **group_name;
group_name = realloc( NULL, 1);
group_name[0] = realloc(NULL ,20);

I have passed this array to a function,

group_count(object, count, group_name);

which uses realloc. it work fines until it populates first four reallocations, but at fifth it gives error.

libc detected *** ./textfileread.exe:  realloc(): invalid next size: 0x08643008

int group_count(struct friends obj[], char cn, char **grp_nm)
{
    int i=0,j=0;
    int grp_cn=0;
    char check=0;
    strcpy(grp_nm[0],obj[0].group);
    grp_cn++;
    grp_count++;

    for(i=1;i<cn;i++) {
        for(j=0;j<grp_cn;j++) {
            if(strcmp(grp_nm[j],obj[i].group)==0)
                check=1;
        }
        if(check==0) {  
            grp_cn++;
            grp_count++;
            printf("\t%d\n",grp_cn);
            grp_nm = realloc( grp_nm, grp_cn);   //at grp_cn=5 allocation gives error
            printf("\t%d\n",grp_nm);
            if(grp_nm == NULL) printf("\t%d\n",grp_cn);  // this 'if' didnt run, means no NULL return
            grp_nm[grp_cn-1] = realloc(NULL ,20);
            strcpy(grp_nm[grp_cn-1],obj[i].group);
        }
    check=0;
    }
}

the output of printf("\t%d\n",grp_nm); is given below, after this at fifth iteration of reallocation

2
140783624
3
140783624
4
140783624
5

*** glibc detected *** ./textfileread.exe: realloc(): invalid next size: 0x099c8008        ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x6b961)[0x17b961]
lib/i386-linux-gnu/libc.so.6(+0x6f1ad)[0x17f1ad]
/lib/i386-linux-gnu/libc.so.6(realloc+0xe9)[0x180579]
./textfileread.exe[0x804934e]
./textfileread.exe[0x8048b42]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xe7)[0x126e37]
./textfileread.exe[0x8048751]
======= Memory map: ========
00110000-0026a000 r-xp 00000000 08:02 1570626    /lib/i386-linux-gnu/libc-2.13.so

after 5 in output on the screen, address should display as it displayed after 4. but it didnt, so why at 5 it give error?

simonc
  • 41,632
  • 12
  • 85
  • 103
Haris_tech
  • 83
  • 1
  • 2
  • 13
  • you should rather use printf("%p",grp_nm) for displaying pointers. That will use meaningful formatting, avoid warnings about ptr-to-int implicit casting and won't trash your output if you happen to use the code on systems that have different int/pointer size. – PypeBros Aug 14 '12 at 08:32

4 Answers4

2

The core of your problem is likely that you're damaging the book-keeping pointers that malloc sets together with your freshly allocated block. When you give that "block" back to realloc, it try to use your damaged pointers to re-insert memory in free zone and other similar activities.

"why 5 and not 4"... most likely because realloc had no need to use one of the formerly returned block before that (e.g. because your block was actually larger than you requested and realloc thinks you'll be fine without re-allocating some memory). malloc/free are complex pieces of software and may show cahotic behaviour when mis-used.

PypeBros
  • 2,607
  • 24
  • 37
  • please can u explain , where i doing this in my code... "(e.g. because your block was actually larger than you requested and realloc thinks you'll be fine without re-allocating some memory). " – Haris_tech Aug 14 '12 at 05:38
  • malloc has a granularity that varies from system to system, but which is usually around 16 bytes. realloc(ptr,5), you're way below and the size of the block allocated (16 bytes) is smaller than the size you think it has. – PypeBros Aug 14 '12 at 08:30
  • joachim's answer is likely to explain how you can fix your code. You also questioned on "why with 5...", and I think being better aware of the inner working of the allocator is the key for that. – PypeBros Aug 14 '12 at 08:37
1

Why use realloc for the initial allocation?

Anyway...

char  **group_name;
group_name = realloc( NULL, 1);
// group_name is now pointing to 1 byte of dynamically allocated memory
group_name[0] = realloc(NULL ,20);
// Whoops. Did we just write 4(or more bytes) into our 1 allocated byte?

I think the same issue exists inside your method.

John3136
  • 28,809
  • 4
  • 51
  • 69
0

Most likely the problem is because you use wrong sizes when you allocate.

char  **group_name;
group_name = realloc( NULL, 1);

but a char ** is not one single byte, it's either four or eight (depending on if you are on a 32 or 64 bit platform). Instead use the sizeof operator:

group_name = realloc( NULL, sizeof *group_name);

And later when you reallocate:

grp_nm = realloc( grp_nm, grp_cn * sizeof *grp_nm);
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    Probably you mean `realloc( NULL, sizeof *group_name);` don't you? – Jens Gustedt Aug 13 '12 at 08:21
  • alright, i will try it, but as far i know, there is no need to to do sizeof as its already 8 bit means 1 byte. I look this in other replies that sizeof needed for int or float type, but its not necessary for char. however i will try , and post the results. – Haris_tech Aug 14 '12 at 05:36
  • @user1570304 A pointer on a 64-bit platform is 8 _bytes_ not 8 _bits_. for `group_name` you are not allocating single character, you are allocating character _pointers_. – Some programmer dude Aug 14 '12 at 06:04
0

thanks. it helped.

   group_name = realloc( NULL, sizeof *group_name); 
    grp_nm = realloc( grp_nm, grp_cn * sizeof *grp_nm); 

after that libc error finished. but sometime i can not read value after array being populated in subroutine i.e in main() i can not read values group_name[3] let suppose. but in subroutine grp_nm[3] displayed very well, where as i have passed the pointer to array group_name in subroutine. the reason what i found is that during realloc if it conflicts with remaining memory, it redefine the whole array to new locaion thus changing the pointer to array. for example, in main group_name=0x5689F0 after i pass it to subroutine, on first reallocation grp_nm=0x5689F0 on second reallocation grp_nm=0x5689F0

and after some reallocations due to memory conflict change in location of array grp_nm will become 0x345FF1. so i have to reuturn this pointer from subroutine like this

     group_name=group_count(object, count, group_name);     

so that if pointer change , it will be updated now group_name=0x345FF1

Haris_tech
  • 83
  • 1
  • 2
  • 13