开发者

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


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.


From the documentation I see that:

HeapReAlloc is guaranteed to preserve the content of the memory being reallocated, even if the new memory is allocated at a different location. The process of preserving the memory content involves a memory copy operation that is potentially very time-consuming.

So the next question would be how do you come to the conclusion that the array contents have changed? Could you provide code? It is possible that there could be pointer issues involved and/or assumptions about where existing pointers now point to (it is important to assume that the operating system call is correct and completely exhaust any possibility your application code could be at fault first because, whilst bugs can exist with an operating system call, it is likely that a bug with a function as important as this would have been noticed before).


After the call to HeapReAlloc the original categoryArray was released so you no longer own it. Other allocations may had reuse it for other purposes and the content may had changed. You need to use the tempArr from now on:

tempArr = (PFEED)HeapReAlloc(heap, HEAP_ZERO_MEMORY, categoryArray, newSize * sizeof(FEED)); 
cetagoryArray = tempArr;


where are you looking after call to HeapRealloc? you should look in the RETURNED pointer, not the original one which was freed by it after your call

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜