views:

1362

answers:

6

Friends

In our C++ , Iam current using realloc method to resize the memory allocated by malloc. realloc() usage is done as below

my_Struct *strPtr =(my_struct*)malloc(sizeof(my_Struct));

/* an later */

strPtr = (my_struct*)realloc(strPtr,sizeof(my_Struct)*NBR);

now wikipeadia (_http://en.wikipedia.org/wiki/Malloc)says that

If instead one did

void *p = malloc(orig_size);

/* and later... */

p = realloc(p, big_size);

then in case it is not possible to obtain big_size bytes of memory, p will have value NULL and we no longer have a pointer to the memory previously allocated for p, creating a memory leak

And it also says that the correct way to rectify the above error is

void *p = malloc(orig_size);

/* and later... */

void *tmp = realloc(p, big_size); 

if (tmp != NULL)
 {

p = tmp; /* OK, assign new, larger storage to p */

} 

else 

{

/* handle the problem somehow */

}


Can you tell me which is the best way to use realloc()

also once I have pointer to a structure and then while using realloc later can i use pointer to a void ???

Many Thanks

+7  A: 

Of course you must protect against the case that realloc() returns NULL. It is a memory allocation, and in C (where realloc()) is mostly used, I think C++ programmers think it is a bit low-level/qaint to use raw realloc() calls, memory allocations can always fail.

Directly overwriting the pointer with the return value is an error, as that drops the original pointer and makes the memory leak in case the reallocation failed.

unwind
C++ programmers tend to think that malloc/realloc don't really know anything about classes and constructors, hence they're not used that much in C++ :).
Timo Geusch
+1  A: 

Use the suggested approach – hold the pointer to the previous buffer until realloc has successfully returned. Once realloc() successfully returns the previous block has been freed and all pointers to it have become dangling – adjust them.

realloc as well as malloc don't care what is the pointer type - you can use void* as well as anything*.

sharptooth
if I use void * for malloc then I will have to use free() 2 times first to release the memory for malloc and then for realloc
ronan
I don't think you need to do so - if the realloc call succeeds, I think it will take care of freeing the previous memory for you if necessary. But I don't remember for sure.
David Zaslavsky
If realloc succeeds the previous block will be freed (like if you've called malloc-memcpy-free). So any pointer to the previous block will now become dangling.
sharptooth
Trying to call free with a pointer to the previous block will usually lead to a program crash - set all those pointers either to the value returned by realloc or to null.
sharptooth
And this will be so regardless of what type pointers you use - malloc/free/realloc all take/return void* and all pointer types are implicitly cast to void*.
sharptooth
Thanks Guys This is what I have now my_Struct *strPtr =(my_struct*)malloc(sizeof(my_Struct));/* an later */my_Struct *newPtr = (my_struct*)realloc(strPtr,sizeof(my_Struct)*NBR);if(newPtrr !=NULL){ strPtr = newPtr; newPtr = NULL;} free(strPtr);
ronan
+4  A: 

Malloc() and realloc() are C functions. Actually, realloc() does malloc() and free() depending on the arguments you pass:

  • If you pass it a null pointer, realloc does what malloc does.
  • If you pass it a zero size, realloc does what free does.

Quoted from Here, where you have a deeper explanation.

The C library makes it impossible to expand a memory block in place, so C++ doesn't support it either.

If you want to stick to C functions, then you should hold the pointer of your first memory allocation when calling realloc(). Then you check if it is NULL, otherwise you assign it, just as you did in your latst code.

But maybe for C++ the best solution is to make your own mallocator, the std solution based on C's malloc(). Check this, or this.

alvatar
There is nothing in the C library that prevents realloc from expanding a memory block in-place. Whether or not this is possible on a given system is dependent upon the implementation.
Dan Moulding
A: 

Like others have said, just use realloc properly as suggested.

But the "C++ way" of doing this is really to use a std::vector<> rather than maintaining arrays yourself. That way the C++ standard library will take care of the low-level details of reallocation (presumably by using realloc()).

janneb
A: 

When realloc() fails and returns NULL the original memory is untouched.
So you should use it like this:

my_Struct* strPtr =(my_struct*)malloc(sizeof(my_Struct));

/* an later */

my_Struct* tmp = (my_struct*)realloc(strPtr,sizeof(my_Struct)*NBR);
if (tmp != NULL)
{
    strPtr = tmp;
}
else
{
    /* realloc Failed. Need to do something */
}
Martin York
A: 

Why are you using malloc and realloc? There's almost always a better way in C++.

If you're using it to make variable-length arrays, you're almost certainly better off with std::vector<>, or perhaps one of the other container templates.

If you're using C instead, perhaps with a C++-capable compiler, then the correct way is the second method, which doesn't lose an entire memory block when it fails to allocate.

The answer to your second question also depends on whether you're using C or C++. In C, void * is a generic data pointer type, and is freely convertible. In C++, void * needs to be explicitly converted. If you're actually writing C, you need to use malloc() and friends, which work on void *. If you're really writing C++, you need to cast, which makes it more awkward. In neither case does realloc() work on pointers to struct, but rather pointers to void.

David Thornley