3

我正在使用 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 数组显示当前数组状态。临时数组显示新的重新分配的数组状态(这是不同的)。

饲料数组:

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

临时数组:

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

请帮忙.. :\

链接到MSDN上的功能说明

4

4 回答 4

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));
    // 剪断...

    如果 (tempArr != NULL)
    {
        // 剪断...
        feedArray = tempArr;

粗体部分应相同。

于 2009-11-19T19:00:42.933 回答
2

从文档中我看到:

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

那么下一个问题是如何得出数组内容已更改的结论?你能提供代码吗?可能存在指针问题和/或关于现有指针现在指向的位置的假设(重要的是假设操作系统调用是正确的并完全排除您的应用程序代码可能首先出错的任何可能性,因为,虽然错误可能存在于操作系统调用中,很可能之前已经注意到具有与此一样重要的功能的错误)。

于 2009-11-19T18:46:14.257 回答
2

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

tempArr = (PFEED)HeapReAlloc(heap, HEAP_ZERO_MEMORY, categoryArray, newSize * sizeof(FEED)); 
cetagoryArray = tempArr;
于 2009-11-19T18:54:38.097 回答
0

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

于 2009-11-19T19:03:10.837 回答