4

I have written following code to get clear with malloc and realloc. I have initialized pointer using malloc and then using realloc, i am increasing the size of the array. But i get following error when i run the code.

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

int main()
{
    char *p;
    p = malloc(10);
    p = " this is it";
    printf("\n%s", p);
    p = realloc(p, 14);
    p[11] = 'A';
    p[12] = 'B';
    p[13] = 'C';
    printf("\n %s", p) ;
    return 0;
}

Output:

ajay@ajay-K54L:~$ gcc te.c 
ajay@ajay-K54L:~$ ./a.out

*** glibc detected *** ./a.out: realloc(): invalid pointer: 0x000000000040071c ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7e626)[0x7fb111e88626]
/lib/x86_64-linux-gnu/libc.so.6(realloc+0x2de)[0x7fb111e8d3ee]
./a.out[0x4005dc]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7fb111e2b76d]
./a.out[0x4004d9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:03 3027043                            /home/ajay/a.out
00600000-00601000 r--p 00000000 08:03 3027043                            /home/ajay/a.out
00601000-00602000 rw-p 00001000 08:03 3027043                            /home/ajay/a.out
00e76000-00e97000 rw-p 00000000 00:00 0                                  [heap]
7fb111bf4000-7fb111c09000 r-xp 00000000 08:03 2100801                    /lib/x86_64-linux-gnu/libgcc_s.so.1
7fb111c09000-7fb111e08000 ---p 00015000 08:03 2100801                    /lib/x86_64-linux-gnu/libgcc_s.so.1
7fb111e08000-7fb111e09000 r--p 00014000 08:03 2100801                    /lib/x86_64-linux-gnu/libgcc_s.so.1
7fb111e09000-7fb111e0a000 rw-p 00015000 08:03 2100801                    /lib/x86_64-linux-gnu/libgcc_s.so.1
7fb111e0a000-7fb111fbd000 r-xp 00000000 08:03 2100780                    /lib/x86_64-linux-gnu/libc-2.15.so
7fb111fbd000-7fb1121bc000 ---p 001b3000 08:03 2100780                    /lib/x86_64-linux-gnu/libc-2.15.so
7fb1121bc000-7fb1121c0000 r--p 001b2000 08:03 2100780                    /lib/x86_64-linux-gnu/libc-2.15.so
7fb1121c0000-7fb1121c2000 rw-p 001b6000 08:03 2100780                    /lib/x86_64-linux-gnu/libc-2.15.so
7fb1121c2000-7fb1121c7000 rw-p 00000000 00:00 0 
7fb1121c7000-7fb1121e9000 r-xp 00000000 08:03 2100760                    /lib/x86_64-linux-gnu/ld-2.15.so
7fb1123d2000-7fb1123d5000 rw-p 00000000 00:00 0 
7fb1123e5000-7fb1123e9000 rw-p 00000000 00:00 0 
7fb1123e9000-7fb1123ea000 r--p 00022000 08:03 2100760                    /lib/x86_64-linux-gnu/ld-2.15.so
7fb1123ea000-7fb1123ec000 rw-p 00023000 08:03 2100760                    /lib/x86_64-linux-gnu/ld-2.15.so
7ffff08d4000-7ffff08f5000 rw-p 00000000 00:00 0                          [stack]
7ffff09ff000-7ffff0a00000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
 this is itAborted (core dumped)

What am i doing wrong with memory allocation? Thank you.

1
  • Regardless of any bugs in the code, don't use realloc Commented Feb 26, 2013 at 13:46

3 Answers 3

8

This:

p = " this is it"; /* Does not copy, use strcpy(). */

assigns the address of the string literal to p, changing it from the address returned previously by malloc(). The pointer being passed to realloc() must be:

... previously allocated by malloc(), calloc() or realloc() and not yet freed with free(), otherwise, the results are undefined.

Change the assignment to strcpy() for example to correct:

p = malloc(12); /* Increased size. */
if (p)
{
    strcpy(p, " this is it");
    char* tmp = realloc(p, 14);  /* Store result in temp to avoid potential */
    if (!tmp)                    /* in the event that realloc() fails. */
    {
        free(p);
        return -1;
    }
    p = tmp;
    /* snip ... */

    free(p); /* When 'p' is no longer required. */
}
Sign up to request clarification or add additional context in comments.

2 Comments

Furthermore, " this is it" requires 12 bytes to store, so even strcpy would not work here as expected since only 10 bytes were allocated. Use strncpy (and be sure to allocated enough memory)
Ajay, depends what you're doing, but realloc is probably not the answer. If it's delimited you can use getdelim / getline on some platforms or other variants on others. Often, pre-allocating a buffer of a certain size should be good enough.
3

You are overwriting the pointer returned by malloc(), with a string:

p = " this is it";

You should use strcpy() to copy the string into the memory pointed at by p:

strcpy(p, "this is it");

Note, though, that the above string requires more space than you allocate: it's 10 visible characters, but strings have a 0-character as terminator so you need at least 11 characters of space.

Also, you should check the return value of both malloc() and realloc() before relying on the pointer being valid. If it's NULL, the allocation failed. This isn't very likely considering your allocation sizes, but it's good practice.

Comments

2
char *p = malloc(10);

allocates the block of memory of size 10 and makes p point to this memory. Then

p = " this is it";

defines a constant string literal and makes p point to the read-only memory, where this constant string literal is stored. So

p = realloc(p, 14);

tries to realloc this read-only memory which produces undefined behavior.


Instead of assigning the address of constant string literal to p (which also procudes a memory leak since the address of the memory that you have dynamically allocated is lost), you should copy this string by using strcpy. So replace this line:

p = " this is it";

with this:

strcpy(p, " this is it");

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.