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

发布于 2024-08-11 18:49:04 字数 1449 浏览 2 评论 0原文

我正在使用 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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

煞人兵器 2024-08-18 18:49:05

从文档中我看到:

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

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

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

九命猫 2024-08-18 18:49:05

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

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

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;
把人绕傻吧 2024-08-18 18:49:05

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

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

城歌 2024-08-18 18:49:04

您引用了特定于 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));
}

这似乎假设第一次分配的大小始终为一。你确定你不是想说if (feedArray == NULL), then allocate newSize * sizeof(FEED)吗?

第二次更新:

好的。另一件值得注意的事情是:

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

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

粗体部分应该是相同的。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文