Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Win32 HeapReAlloc() changes values?

I'm writing an app in C using win32 API. When I try to enlarge the size of my array, using the HeapRealloc() function, it changes my current values in the array, instead of copying them. The code I use to reallocate memory:

BOOL ChangeFeedArraySize(UINT newSize)
{   
    char tempChar[20] = "";
    PFEED tempArr;
    if (newSize == 1)
    {
        tempArr = (PFEED)HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(FEED));
    }
    else
    {
        tempArr = (PFEED)HeapReAlloc(heap, HEAP_ZERO_MEMORY, categoryArray, newSize * sizeof(FEED));
        // FEED - a struct
        // PFEED - a pointer to the struct
        // categoryArray - array to be reallocated
    }

    if (tempArr != NULL)
    {
        MessageBox(NULL, ltoa(HeapSize(heap, 0, tempArr),tempChar,10) , "Heap size after reallocation", MB_OK | MB_ICONEXCLAMATION);
        feedArray = tempArr;
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

Here is the status of the arrays when in breakpoint. the feed array shows the current array state. the temp array show the new reallocated array state (which is different).

feed array:

feedArray http://www.freeimagehosting.net/uploads/526b0b2172.jpg

temp array:

tempArray http://www.freeimagehosting.net/uploads/17858f2e7e.jpg

Please help.. :\

Link to the function description on MSDN

like image 254
idcman Avatar asked Jun 11 '26 04:06

idcman


1 Answers

You cite a Windows-specific function, but this is also true of realloc(), which is the standard equivalent.

If these functions return the same address as passed in, it's because the memory right after the buffer you asked for originally is unused. So it can satisfy the request without moving the buffer.

But what if there were two quick allocations in immediate succession, for example? Maybe the memory right after what was originally requested ended up being used for the next allocation. In which case, the allocator needs to find space somewhere else, copy what was in the old buffer, free the old buffer, and return the new one.

Generally, the pattern you want to follow for this sort of thing is like this:

void *newmem = realloc(oldmem, newsize);
if (!newmem)
{
   // TODO: handle failure
   // possibly free(oldmem); depending on how you want to handle errors
}
else
{
   oldmem = newmem;
}

A common shortcut that people take is "oldmem = realloc(oldmem, newsize);", but this is not as graceful as the above, as it leaks oldmem when there is a failure.

Update based on your edit:

One thing I'm wondering about in your code is this part:

if (newSize == 1)
{
    tempArr = (PFEED)HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(FEED));
}

This seems to assume that the first allocation will always be of size one. Are you sure you didn't mean to say if (feedArray == NULL), then allocate newSize * sizeof(FEED)?

Second update:

OK. The other thing that stands out is this:

    tempArr = (PFEED)HeapReAlloc(heap, HEAP_ZERO_MEMORY, categoryArray,
                                 newSize * sizeof(FEED));
    // Snip...

    if (tempArr != NULL)
    {
        // Snip...
        feedArray = tempArr;

The bolded parts should be the same.

like image 115
asveikau Avatar answered Jun 13 '26 03:06

asveikau



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!