views:

876

answers:

10
int main()
{
   char myString = NULL;
   realloc(&myString, 5);
   strncpy((char *)&myString, "test", 5);
}

Seems to work Fine but, i'm still slightly confused about stack vs heap, is this allowed? Does myString need to be freed manually or will it be released when it goes out of scope?


Edit: Thanks for the responses, so i presume this is equally illegal

//I want the code to change myString to "tests"
char myString[5] = "test";
realloc(&myString, strlen(myString)+2);
myString[4] = 's';
myString[5] = '\0';
+3  A: 

This shouldn't work. You're reallocing something that wasn't malloced in the first place. And no, it won't get freed when it goes out of scope - when you use malloc or realloc, it's all up to you.

Update: Your edit doesn't change anything - you're still trying to realloc something that wasn't malloced in the first place. Also, you can't ignore the return value from realloc - if realloc has to move the memory somewhere else, you'll find that in the return. In other words:

char* ptr = malloc(4);
ptr = realloc(ptr, 5);

After realloc, ptr might be pointing to an entirely different place in memory, and continuing to use the original value of ptr could leave you using memory that's been freed and which isn't as big as you think it is.

Paul Tomblin
This is fine. realloc() is an extremely versatile function (too versatile, in my opinion), and will do all memory management.
David Thornley
@David, not it's not ok - realloc can reassign pointers, and you can't reassign a variable on the stack like that.
Paul Tomblin
David Thornley
@Paul, shouldn't you use a temporary pointer variable to store the return value of realloc, in the event that it returns NULL, your original memory will still be allocated and can never be freed.
dreamlax
@dreamlax - good point.
Paul Tomblin
+5  A: 

Some problems with the code you posted:

  • Yes you need to free everything you allocate with malloc, and realloc, and the other related C style memory allocation functions.
  • I think you meant to have char *myString, not char. Passing in the address of something on the stack (your char) is completely wrong.
  • You need to initialize your myString char pointer to NULL before using it in realloc.
  • You should be passing 4 into strncpy not 5, if you had a larger string you'd be overwriting memory.
  • You should be freeing the buffer you created in your example
  • You should be checking the return value of your realloc call. realloc()

[Regarding realloc's return value:] Upon successful completion with a size not equal to 0, realloc() returns a pointer to the (possibly moved) allocated space. If size is 0, either a null pointer or a unique pointer that can be successfully passed to free() is returned. If there is not enough available memory, realloc() returns a null pointer and sets errno to [ENOMEM].

  • re-alloc will work like malloc when you pass in NULL:

If ptr is a null pointer, realloc() behaves like malloc() for the specified size.

A more C++ way to do it:

You tagged this as C++ though, and it's more type safe to use C++'s new operator. Although the new operator does not allow for re-allocations, it will work for allocations and for re-using existing buffers (placement new).

char *myString = new char[5];
strncpy(myString, "test", 4); 
//...
delete[] myString;

or even:

#include <string>

//...

std::string str = "test";

Source of top 2 quotes

Brian R. Bondy
It is defined to use realloc() with NULL. You could do all C memory management with realloc(). Whether this is a good idea or not is another question.
David Thornley
You are the only person so far to mention the fact that this isn't even the C++ way to manage memory. You get +1 from me.
Brad Barker
+18  A: 

No, this is completely wrong. realloc should only be used to reallocate memory allocated by malloc, what you are doing works only by accident, and will eventually crash horribly

char *myString = malloc(x);
myString = realloc(myString,y);
free(myString)

You are better off using new and delete, and even better off using std::string, however.

David Sykes
You could also get away with "char *myString = NULL;" and reallocing a null pointer.
Paul Tomblin
+1  A: 

THIS IS DANGEROUS! This will corrupt your stack. If you were to realloc something on the stack of a function that then returned to main(), you would actually end up overwriting the stack frame and returning somewhere other than main(). THIS IS A POTENTIAL SECURITY HOLE.

Try running the following. If it crashes on realloc, you got lucky. You can do serious damage with something like memcpy(&myString).

int dostuff();

int main()
{
        dostuff();
        return 0;
}

int dostuff()
{
        char myString = NULL;
        realloc(&myString, 5);
        strncpy((char *)&myString, "test", 5);
        return 0;
}
Matt Kane
A: 

Yes, you still need to free myString.

malloc, realloc and free are all operating on the heap, not on the stack. The variable myString exists on the stack, the data that it points to is on the heap.

Prior statements about passing in NULL as being undefined are incorrect. The standard is that realloc(NULL, newsize) is the equivalent of malloc(newsize).

Has been for quite a while.

Petesh
A: 

You do not have to free myString since it is on the stack (which gets "freed" when leaving scope).

realloc is illegal here, the address has to be NULL or an address returned by an earlier call to realloc, malloc or calloc.

Every variable you declare is on the stack, even a pointer:

int *x;

The variable x is on the stack! It is of type pointer and holds an address.

x = (int *)malloc(sizeof(int));

assigns the address returned by malloc to the variable x! The content of x is an memory address!

Johannes Weiß
+1  A: 

This is what you should never do. Trying to free() or realloc() a stack variable can lead to undefined behaviour including (but not limited to) corrupted stack (leading to unpredictable flow of control), corrupted heap service structures, corrupted user memory. You're lucky if the program just crashes with an AV. It may work in some cases, but you should never try to do so.

Rule of thumb: only return memory to the memory manager it was allocated on. In this case don't try to return the stack variable to the runtime heap.

sharptooth
A: 

The problem with what you're doing is that you're mucking with something that isn't a variable. You defined myString as a char, and are therefore trying to change its address. That's bad.

The function realloc() isn't supposed to change anything passed into it. It takes a pointer to some memory on the heap (or the null pointer, if nothing's already allocated) and returns a pointer to some memory on the heap.

Therefore, you provide either a null pointer or a pointer to something allocated by malloc() or realloc() or calloc(), and store the pointer returned.

Something like

char * myString = NULL;
myString = realloc(myString, 5);

will work, but you will want to free() myString.

In C++, however, use std::string.

David Thornley
A: 

In response to your second code example:

Yes, this is also illegal. myString is not allocated with malloc (or calloc), so it can't be reallocated with realloc, or freed with free.

Plus that realloc doesn't take a pointer to a pointer as its first argument. It takes a pointer to allocated memory, and returns another (possibly different) pointer. Write the call like this instead:

myString = realloc(myString, strlen(myString)+2);
Thomas Padron-McCarthy
A: