【问题标题】:Why Win32 HeapReAlloc() changes values?为什么 Win32 HeapReAlloc() 会改变值?
【发布时间】:2010-12-18 10:37:01
【问题描述】:

我正在使用 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上的功能描述

【问题讨论】:

  • 我似乎误导了你,所以我添加了完整的相关代码。还添加了屏幕截图。谢谢大家的回复:)

标签: c winapi memory-management heap-memory realloc


【解决方案1】:

从文档中我看到:

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

      粗体部分应该是一样的。

      【讨论】:

      • 不,我很确定.. 只有在第一次调用时,newSize 才等于 1。在重新分配后,数组已损坏,就像我在屏幕截图中显示的那样...
      • 第二次更新:不明白你的意思:\ 我正在检查分配的内存不是 NULL,如果不是,我开始将它用作我的永久数组。再次感谢。
      • 刚刚意识到我是个笨蛋!非常感谢!我混淆了两个相似的功能。
      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-20
        • 1970-01-01
        • 2012-04-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多