1
char *t = malloc(2);
t = "as";

t = realloc(t,sizeof(char)*6);

I am getting error "invalid pointer: 0x080488d4 *"..

I am getting strange errors in using memory allocation functions. Is there any good tuts/guides which could explain me memory allocation functions. I am using linux..

Please help..

4
  • 1
    sizeof(char) is defined as 1. It's one of the few things you can always count on. No need to multiply by it. Commented Oct 14, 2011 at 19:28
  • I'd be willing to state that using realloc() at all is probably an error... Commented Oct 14, 2011 at 19:43
  • @MichaelDorgan, thats a pretty bold statement. There are plenty of situations where realloc is just fine. Commented Oct 14, 2011 at 19:47
  • I intended it to be. Every place I've ever seen realloc used has been a massive hack to get around properly getting your buffers sized to start with. Yes, there are places where you won't know your size coming in, but typically I see realloc in a for loop or something equally lame. Also, in embedded land, realloc is really bad at creating memory fragmentation. Commented Oct 14, 2011 at 19:51

5 Answers 5

5

This is your problem:

char *t = malloc(2);
t = "as";

You probably thought this would copy the two-character string "as" into the buffer you just allocated. What it actually does is throw away (leak) the buffer, and change the pointer to instead point to the string constant "as", which is stored in read-only memory next to the machine code, not on the malloc heap. Because it's not on the heap, realloc looks at the pointer and says "no can do, that's not one of mine". (The computer is being nice to you by giving you this error; when you give realloc a pointer that wasn't returned by malloc or realloc, the computer is allowed to make demons fly out of your nose if it wants.)

This is how to do what you meant to do:

char *t = malloc(3);
strcpy(t, "as");

Note that you need space for three characters, not two, because of the implicit NUL terminator.

By the way, you never need to multiply anything by sizeof(char); it is 1 by definition.

Sign up to request clarification or add additional context in comments.

2 Comments

Don't use strcpy. Use strncpy.
strcpy is safe in this case, and strncpy has weird semantics that make it rarely the right thing. What you really want is strlcpy, shame that isn't standard. Or, really in this case what you want is strdup, which is also, alas, not standard.
3

That is not how you assign strings in C.

The correct syntax is:

char* t = malloc(3);  // Reserve enough space for the null-terminator \0

strncpy(t, "as", 3);
// Copy up to 3 bytes from static string "as" to char* t.
// By specifying a maximum of 3 bytes, prevent buffer-overruns

Allocating 2-bytes is NOT enough for "as".
C-strings have a 1-byte null-terminator, so you need at least 3 bytes to hold "as\0".
(\0 represents the null-terminator)

The code you wrote: t = "as"; makes the pointer t "abandon" the formerly allocated memory, and instead point to the static string "as". The memory allocated with malloc is "leaked" and cannot be recovered (until the program terminates and the OS reclaims it).

After this, you can call realloc as you originally did.
However, you should not do t = realloc(t,6);. If realloc fails for any reason, you've lost your memory.

The preferred method is:

new_t = realloc(t, 6);
if (new_t != NULL)  // realloc succeeded
{   t = new_t;  
}
else
{  // Error in reallocating, but at least t still points to good memory!
}

2 Comments

Note though that strncpy doesn't always create a string. e.g. strncpy(t,"foo",3); would happily copy the 3 letters in foo over to t , which is fine, it has room for 3 chars. However t ends up not nul terminated in that case, so you can't treat it as a C string afterwards.
strncpy will tell you if it successfully copied a C-string. After strncpy(dest, src, n), (dest[n-1] == '\0') will be true if there was sufficient space, or false if your "foo",3 example.
2

Your code reassigns t, making it point elsewhere

char *t = malloc(2); //t=0xf00ba12
t = "as"; //t=0xbeefbeef
t = realloc(t,sizeof(char)*6); //confused because t is 0xbeefbeef, not 0xf00b412.

Instead use strcpy

char *t = malloc(3); //don't forget about the '\0'
strcpy(t, "as");
t = realloc(t, 6); //now the string has room to breathe

Comments

0

First off, don't do that:

char *t = malloc(2);

Do this instead:

char *t = malloc(2 * sizeof(char));
/* or this: */
char *t = calloc(2, sizeof(char));

It may not seem worth the effort, but otherwise you may run into problems later when you deal with types larger than 1 byte.

In this line:

t = "as";

You're assigning the address of the string literal "as", so your pointer no longer points to the memory you allocated. You need to copy the contents of the literal to your allocated memory:

char *t = calloc(3, sizeof(char));
/* "ar" is 3 char's: 'a', 'r' and the terminating 0 byte. */
strncpy(t, "ar", 3);
/* then later: */
t = realloc(t,sizeof(char)*6);

You can also just use strdup, which is safer:

#include <string.h>

char *t = strdup("ar");
t = realloc(t,sizeof(char)*6);

And don't forget to free the memory

free(t);

Comments

0
char *t = malloc(2);

this means you have created a pointer to a memory location that can hold 2 bytes

     +-+-+ 
t -> | | |
     +-+-+ 

when you do

t = "as";

now you made t point to somewhere else than what it originally was pointing to. now it no longer points to the heap

t = realloc(t,sizeof(char)*6);

now you are taking the pointer pointing to read only memory and try to realloc it.

when you use malloc you allocate space on the heap. t in this case is a pointer to that location, an address of where the block is.

in order to put something in that spot you need to copy the data there by dereferencing t, this is done by writing * in front of t:

*t = 'a';   // now 'a' is where t points
*(t+1)='s'; // now 's' is behind a, t still pointing to 'a'

however in C, a string is always terminated with a 0 (ASCII value) written as '\0' so in order to make it a string you need to append a \0

     +-+-+--+ 
t -> |a|s|\0|
     +-+-+--+ 

in order to do this you need to malloc 3 bytes instead, than you can add the \0 by writing *(t+2)='\0';

now t can be treated as pointing to a string and used in functions that takes strings as arguments e.g. strlen( t ) returns 2

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.