Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to free reallocated memory? C++

I'm trying to free memory that's reallocated but I get an error...

float * foo = NULL;
float * bar = NULL;

void update()
{
    ...
    foo = (float *)malloc( a * 2 * sizeof(float));
    ...
    bar = (float *)realloc( foo, a * 2 * sizeof(float));
    ...
    free( foo );
    ...
    // when i do
    if(bar != NULL)
    {
        free(bar); // <-- error at executing
    }
}

I get error: http://d.pr/mpBF and visual studio shows me the following file:

osfinfo.c
=========
void __cdecl _unlock_fhandle (
        int fh
        )
{
        LeaveCriticalSection( &(_pioinfo(fh)->lock) );
}

Any ideas?

like image 308
JohnnyAce Avatar asked Mar 27 '12 15:03

JohnnyAce


People also ask

How do you deallocate memory in C?

In C, the library function malloc is used to allocate a block of memory on the heap. The program accesses this block of memory via a pointer that malloc returns. When the memory is no longer needed, the pointer is passed to free which deallocates the memory so that it can be used for other purposes.

Why do we free memory in C?

However on long running programs, failing to free memory means you will be consuming a finite resource without replenishing it. Eventually it will run out and your program will rudely crash. This is why you must free memory.

What does the free () function do in C?

When memory blocks are allotted by calloc(), malloc(), or realloc() functions, the C library function free() is used to deallocate or release the memory blocks to reduce their wastage. free() function in C should only be used either for the pointers pointing to the memory allocated using malloc() or for a NULL pointer.


4 Answers

foo = (float *)malloc( a * 2 * sizeof(float));
bar = (float *)realloc( foo, a * 2 * sizeof(float));
free( foo ); // oops, foo has gone

At the point at which you call free(foo), foo is invalid since it was already freed when you called realloc.

The code should be something like this pseudo-code:

foo = (float *)malloc( a * 2 * sizeof(float));
if (foo == NULL) 
    return ERROR_CODE;
...
bar = (float *)realloc( foo, a * 2 * sizeof(float));
if (bar == NULL) 
{
    free(foo);
    return ERROR_CODE;
}
...
free(bar);
return SUCCESS;

Of course, since this is C++, you should be avoiding malloc and free altogether and using std::vector<float>.

like image 179
David Heffernan Avatar answered Oct 06 '22 22:10

David Heffernan


When you realloc memory you should not free the old memory.

bar = (float *)realloc( foo, a * 2 * sizeof(float));
free( foo ); // <-- this is wrong

You want:

float * foo = NULL;

void update()
{
    ...
    foo = (float *)malloc( a * 2 * sizeof(float));
    ...
    float * bar = (float *)realloc( foo, a * 2 * sizeof(float));
    if(bar)
       foo = bar;
    ...
    free(foo);
}
like image 45
bames53 Avatar answered Oct 06 '22 20:10

bames53


My guess is that the realloc call manages to extend the memory allocated by the call to malloc. In this case both foo and bar will point to the same memory address, and you're freeing foo somewhere before trying to free bar resulting in a double deletion.

You do not need to free( foo ) at all because realloc will do that for you if the memory area was moved during reallocation. From the linked page:

If the area pointed to was moved, a free(ptr) is done.

like image 40
Praetorian Avatar answered Oct 06 '22 20:10

Praetorian


Once you've passed a pointer to realloc(), it is formally deallocated (freed) and you must not free it again.

C99 §7.20.3.4 The realloc function

2 The realloc function deallocates the old object pointed to by ptr and returns a pointer to a new object that has the size specified by size. The contents of the new object shall be the same as that of the old object prior to deallocation, up to the lesser of the new and old sizes. Any bytes in the new object beyond the size of the old object have indeterminate values.

It may happen that realloc() returns the same pointer as it was given, but you cannot assume that it will in general. And once you've passed a pointer to realloc() (or free()) you must assume it is no longer a valid pointer.

The rules in C++ are basically the same; it incorporates the C89 standard for functions from C such as realloc().

Your system is correct to complain that you're freeing unallocated memory.

like image 1
Jonathan Leffler Avatar answered Oct 06 '22 21:10

Jonathan Leffler