Search code examples
cmemoryrealloc

realloc says Invalid next size


Here is my code which should dynamically allocate memory for storing strings:

#define _XOPEN_SOURCE 700

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

int main()
{
    char **path = NULL;

    path = (char **) malloc(sizeof(char *));

    for (int i = 0; i < 5; i++)
    {
            path[i] = strdup("TEST");
            path = (char **) realloc(path, sizeof(char *));
    }

    for (int i = 0; i < 5; i++)
    {
            printf("%s\n", path[i]);
    }

    return 0;
}

The above code breaks on the line where i have reallocated the memory.

According to me the the memory allocated to path on first malloc is as given below:

path -----> |   char *  | // path points to a character pointer which       inturn is pointing to nothing(Dangling).

So, at this point of time when the program ran the line:

path = (char **) malloc(sizeof(char *));

path[0] is currently in bounds and we can store starting address of one and only one string at path[0] and path[1] should be out of bounds at this point of time.

So, when the very first time we entered the for loop where we are storing the address of string at path[i] we will be able to that as:

path[0] = strdup("TEST"); // is in bounds.

To store another string we need some more memory that path should be pointing. So i did realloc in the line just below as:

path = (char **) realloc(path, (char *));

So, according to me path should look like this in memory as below:

path --------->|old char *|----->"TEST"
  |----------->|new char *|----->(Dangling) // Pointing Nowhere.

So, now path[1] is also in bounds and we should be able to use that memory location. So i can't figure out why i am getting this Segmentation fault when i run my code:

*** glibc detected *** ./dynamic: realloc(): invalid next size: 0x0000000000602010 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x75018)[0x7f743153e018]
/lib64/libc.so.6(+0x7ae96)[0x7f7431543e96]
/lib64/libc.so.6(realloc+0xfa)[0x7f74315441aa]
./dynamic[0x40067f]
/lib64/libc.so.6(__libc_start_main+0xe6)[0x7f74314e7bc6]
./dynamic[0x400569]
======= Memory map: ========
00400000-00401000 r-xp 00000000 00:27 14459340                           /home/xpansat/c/basic/dynamic
00600000-00601000 r--p 00000000 00:27 14459340                           /home/xpansat/c/basic/dynamic
00601000-00602000 rw-p 00001000 00:27 14459340                           /home/xpansat/c/basic/dynamic
00602000-00623000 rw-p 00000000 00:00 0                                  [heap]
7f742c000000-7f742c021000 rw-p 00000000 00:00 0 
7f742c021000-7f7430000000 ---p 00000000 00:00 0 
7f74312b2000-7f74312c8000 r-xp 00000000 fd:01 173                        /lib64/libgcc_s.so.1
7f74312c8000-7f74314c7000 ---p 00016000 fd:01 173                        /lib64/libgcc_s.so.1
7f74314c7000-7f74314c8000 r--p 00015000 fd:01 173                        /lib64/libgcc_s.so.1
7f74314c8000-7f74314c9000 rw-p 00016000 fd:01 173                        /lib64/libgcc_s.so.1
7f74314c9000-7f743161d000 r-xp 00000000 fd:01 27                         /lib64/libc-2.11.1.so
7f743161d000-7f743181d000 ---p 00154000 fd:01 27                         /lib64/libc-2.11.1.so
7f743181d000-7f7431821000 r--p 00154000 fd:01 27                         /lib64/libc-2.11.1.so
7f7431821000-7f7431822000 rw-p 00158000 fd:01 27                         /lib64/libc-2.11.1.so
7f7431822000-7f7431827000 rw-p 00000000 00:00 0 
7f7431827000-7f7431846000 r-xp 00000000 fd:01 20                         /lib64/ld-2.11.1.so
7f7431a14000-7f7431a17000 rw-p 00000000 00:00 0 
7f7431a44000-7f7431a45000 rw-p 00000000 00:00 0 
7f7431a45000-7f7431a46000 r--p 0001e000 fd:01 20                         /lib64/ld-2.11.1.so
7f7431a46000-7f7431a47000 rw-p 0001f000 fd:01 20                         /lib64/ld-2.11.1.so
7f7431a47000-7f7431a48000 rw-p 00000000 00:00 0 
7fff62f8c000-7fff62fa2000 rw-p 00000000 00:00 0                          [stack]
7fff62fff000-7fff63000000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

I can't figure what i am doing wrong, because i was able to run my code if i changed my realloc line as below:

path = (char **) realloc(sizeof(char *)*8);

If is did that multiplication by 8 my code runs but i want to allocate exact memory i want, Any ideas why it is not working without that multiply by 8.


Solution

  • Here

    path = (char **) malloc(sizeof(char *));
    

    you are allocating a pointer to a pointer to char, that is space for one pointer to a C-"string".

    Then here:

    for (int i = 0; i < 5; i++)
    {
       path[i] = strdup("TEST");
       path = (char **) realloc(path, sizeof(char *));
    }
    

    you not only use one pointer to a C-"string" but reallocation for more does nothing more then just reallocate the same size as before, but infact you access as if you added memory for one more pointer in each iteration.

    Doing so you overwrite memory not allocated (or alrerady in use by something else) and mess up the programs memory management.

    A somewhat more straight forward approach to this would be:

      ...
    
      char ** path = NULL;
    
      for (size_t i = 0; i < 5; ++i)
      {
        path = realloc(path, (i+1) * sizeof(*path));
        path[i] = strdup("TEST");
      }
    
      ...