-2

Im trying to reallocate a double char pointer dynamicly in a larger program and im always getting that error "realloc(): invalid next size", so i wrote a smaller test to show u guy my exact problem:

my little test:

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

int main(void){
    char **buf = malloc(sizeof(char*));
    for(int i = 0; i < 20; i++){
        buf[i] = malloc(sizeof(char) * 6);
        strcpy(buf[i], "hallo");
        printf("%s\n", buf[i]);
        if( (realloc(buf, sizeof(char*) * (i+1))) == NULL) exit(-1);
    }

    return 0;
}

this is always crashing at the 4th reallocation with the full error message:

Error in `./myTest': realloc(): invalid next size: 0x0000000001cb2010 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f450a4a97e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x834aa)[0x7f450a4b54aa]
/lib/x86_64-linux-gnu/libc.so.6(realloc+0x179)[0x7f450a4b6839]
./myTest[0x40069c]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f450a452830]
./myTest[0x400529]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:01 663159                             
/home/qbongo/BS-PK-2017/10_pk/myTest
00600000-00601000 r--p 00000000 08:01 663159                             
/home/qbongo/BS-PK-2017/10_pk/myTest
00601000-00602000 rw-p 00001000 08:01 663159                             
/home/qbongo/BS-PK-2017/10_pk/myTest
01cb2000-01cd3000 rw-p 00000000 00:00 0                                  [heap]
7f4504000000-7f4504021000 rw-p 00000000 00:00 0 
7f4504021000-7f4508000000 ---p 00000000 00:00 0 
7f450a21c000-7f450a232000 r-xp 00000000 08:01 398530                     
/lib/x86_64-linux-gnu/libgcc_s.so.1
7f450a232000-7f450a431000 ---p 00016000 08:01 398530                     
/lib/x86_64-linux-gnu/libgcc_s.so.1
7f450a431000-7f450a432000 rw-p 00015000 08:01 398530                     
/lib/x86_64-linux-gnu/libgcc_s.so.1
7f450a432000-7f450a5f2000 r-xp 00000000 08:01 394742                     
/lib/x86_64-linux-gnu/libc-2.23.so
7f450a5f2000-7f450a7f2000 ---p 001c0000 08:01 394742                     
/lib/x86_64-linux-gnu/libc-2.23.so
7f450a7f2000-7f450a7f6000 r--p 001c0000 08:01 394742                     
/lib/x86_64-linux-gnu/libc-2.23.so
7f450a7f6000-7f450a7f8000 rw-p 001c4000 08:01 394742                     
/lib/x86_64-linux-gnu/libc-2.23.so
7f450a7f8000-7f450a7fc000 rw-p 00000000 00:00 0 
7f450a7fc000-7f450a822000 r-xp 00000000 08:01 393312                     
/lib/x86_64-linux-gnu/ld-2.23.so
7f450aa07000-7f450aa0a000 rw-p 00000000 00:00 0 
7f450aa20000-7f450aa21000 rw-p 00000000 00:00 0 
7f450aa21000-7f450aa22000 r--p 00025000 08:01 393312                     
/lib/x86_64-linux-gnu/ld-2.23.so
7f450aa22000-7f450aa23000 rw-p 00026000 08:01 393312                     
/lib/x86_64-linux-gnu/ld-2.23.so
7f450aa23000-7f450aa24000 rw-p 00000000 00:00 0 
7ffcc108f000-7ffcc10b0000 rw-p 00000000 00:00 0                          [stack]
7ffcc1149000-7ffcc114b000 r--p 00000000 00:00 0                          [vvar]
7ffcc114b000-7ffcc114d000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  
[vsyscall]
Aborted (core dumped)
gsamaras
  • 71,951
  • 46
  • 188
  • 305
Qbongo
  • 11
  • 2

3 Answers3

1

By invoking char **buf = malloc(sizeof(char*)); you are allocating just a single pointer, not an array of them.

const size_t items_count = 20;
char **buf = malloc(sizeof(char*) * items_count);
for(int i = 0; i < items_count; i++){
    buf[i] = malloc(sizeof(char) * 6); // now we won't access array out of bounds here
// no need to realloc
user7860670
  • 35,849
  • 4
  • 58
  • 84
  • 1
    But he reallocates on each iteration. I don't think this code is the actual code, but just an example to show at which iteration `realloc` fails. – vgru Jan 26 '18 at 08:21
  • @Groo Realoc code is wrong (it will realoc the same amount of bytes) and rather pointless when array size is known in advance. – user7860670 Jan 26 '18 at 08:23
  • yes, i want to invoke the next pointer of the array with the line if( (realloc(buf, sizeof(char*) * (i+1))) == NULL) exit(-1); – Qbongo Jan 26 '18 at 08:24
  • @Qbongo What do you mean by "invoke the next pointer of the array"? – user7860670 Jan 26 '18 at 08:26
  • @Groo you are totally right, its just an example to point out the issue – Qbongo Jan 26 '18 at 08:26
  • @VTT the plan is to allocate the next pointer of the next string right befor its needed. but its crashing always at the 4th reallocation – Qbongo Jan 26 '18 at 08:28
  • @Qbongo But you already know required array size, reallocating array on each iteration would be inefficient. – user7860670 Jan 26 '18 at 08:30
  • @VTT: This isn't OP's actual code, the length most likely isn't known in advance. – vgru Jan 26 '18 at 08:33
1

It's supposed to be:

buf = realloc(buf, sizeof(char*) * (i+2));
  1. Your code is simply throwing away the result of realloc.
  2. You need to allocate (i+2) if you are doing it at the end of the iteration.

I am presuming this isn't your actual code, but it would make more sense to move realloc to the top of the loop (check the first example for realloc on this page), something like:

for(int i = 0; i < 20; i++)
{
    buf = realloc(buf, sizeof(char*) * (i+1));
    if (buf == NULL)
        exit(-1);

    ...
}

(update)

According to @coderredoc's comments below, although exit will free all memory associated with the process, keep in mind that good programming practice would be to free the previously allocated pointer, in case realloc fails:

char **buf = malloc(sizeof(char*));
for (int i = 0; i < 20; i++)
{
    // try to realloc
    {
        char ** larger = realloc(buf, sizeof(char*) * (i + 1));
        if (larger) 
        {
            buf = larger;
        }
        else 
        {
            // realloc failed, we might need to free individual items
            // if we are not going to use them anymore
            for (int k = 0; k < (i - 1); k++) free(buf[k]);

            // we should free previous buff also
            free(buff);

            // we can exit, or break the loop, or whatever
            exit(-1);
        }
    }

    // do stuff here
    ...
}
vgru
  • 49,838
  • 16
  • 120
  • 201
  • 1
    @coderredoc: I updated the answer with your comments anyway, someone will find these details useful, thanks! – vgru Jan 26 '18 at 08:58
1

I see 2 errors in your code.

  1. You're not storing in buf the new address returned by realloc. When the new space required is not available in place, realloc allocates a new space somewhere else in memory.

  2. Your loop starts at i = 0, therefor the first time you reach realloc, you're expected to allocate two elements: i+2 instead of i+1

yoones
  • 2,394
  • 1
  • 16
  • 20