为什么Win32 HeapReAlloc()会改变值?

时间:2009-11-19 18:32:14

标签: c winapi memory-management heap realloc

我正在使用win32 API在C中编写应用程序。 当我尝试使用HeapRealloc()函数扩大数组的大小时,它会更改数组中的当前值,而不是复制它们。 我用来重新分配内存的代码:

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

以下是断点时数组的状态。 feed数组显示当前的数组状态。 temp数组显示新的重新分配的数组状态(不同)。

Feed数组:

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

临时数组:

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

请帮助..:\

链接到MSDN

上的功能说明

4 个答案:

答案 0 :(得分:6)

您引用了Windows特定的功能,但realloc()也是如此,这是标准的等效功能。

如果这些函数返回与传入的地址相同的地址,那是因为您最初请求的缓冲区之后的内存未使用。所以它可以在不移动缓冲区的情况下满足请求。

但是,例如,如果有两个快速分配,那会怎么样?也许在最初请求之后的内存最终被用于下一次分配。在这种情况下,分配器需要在其他地方找到空间,复制旧缓冲区中的内容,释放旧缓冲区,然后返回新缓冲区。

通常,您想要遵循此类事情的模式是这样的:

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

人们采用的常见快捷方式是“oldmem = realloc(oldmem, newsize);”,但这并不像上面那样优雅,因为它在发生故障时会泄漏oldmem

根据您的修改进行更新

我在你的代码中想知道的一件事就是这部分:

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

这似乎假设第一次分配总是大小为1。您确定不想说if (feedArray == NULL),然后分配newSize * sizeof(FEED)吗?

第二次更新:

行。另一个突出的是:

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

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

粗体部分应该相同。

答案 1 :(得分:2)

从文档中我看到:

即使新内存分配在不同的位置,HeapReAlloc也可以保证重新分配的内存内容。保留存储器内容的过程涉及可能非常耗时的存储器复制操作。

那么下一个问题是你如何得出阵列内容已经改变的结论?你能提供代码吗?可能存在涉及指针问题和/或关于现有指针现在指向的假设(重要的是假设操作系统调用是正确的并且完全耗尽应用程序代码可能首先出错的可能性,因为,尽管操作系统调用可能存在错误,可能之前已经注意到具有与此重要功能的错误。)

答案 2 :(得分:2)

在调用HeapReAlloc之后,原来的categoryArray被释放,因此您不再拥有它。其他分配可能会将其重新用于其他目的,并且内容可能已更改。从现在开始,您需要使用tempArr:

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

答案 3 :(得分:0)

你在调用HeapRealloc后在哪里?您应该查看 RETURNED 指针,而不是调用后被其释放的原始指针