JohnnyAce
JohnnyAce

Reputation: 3749

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?

Upvotes: 8

Views: 2896

Answers (4)

bames53
bames53

Reputation: 88225

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);
}

Upvotes: 2

Jonathan Leffler
Jonathan Leffler

Reputation: 755064

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.

Upvotes: 1

David Heffernan
David Heffernan

Reputation: 613572

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>.

Upvotes: 6

Praetorian
Praetorian

Reputation: 109289

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.

Upvotes: 2

Related Questions