【问题标题】:Why won't realloc work in this example?为什么 realloc 在这个例子中不起作用?
【发布时间】:2012-11-07 20:12:39
【问题描述】:

我的教授给了我们一个“作业”来找出为什么 realloc() 在这个特定示例中不起作用。 我尝试搜索此站点,但我认为它不起作用,因为没有真正的方法来确定分配给 malloc() 的内存块的大小,所以 realloc() 不知道它所分配的内存块的新大小需要重新分配。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
int main ()
{
    MEMORYSTATUS memInfo;
    memInfo.dwLength = sizeof(MEMORYSTATUS);
    GlobalMemoryStatus(&memInfo);
    double slobodno = memInfo.dwAvailVirtual/1024./1024.;

    printf("%g MB\n",slobodno);
    int br=0,i,j;

    char **imena,*ime,*temp,*bbb=NULL;
    imena=(char**) malloc(sizeof(char*)*(br+1));
    while(1)
    {
        printf("Unesite ime: ");
        ime=(char*) malloc(sizeof(char)*4000000);
        gets(ime);
        printf("%u\n", strlen(ime));
        ime=(char*) realloc(ime,strlen(ime)+1);

        GlobalMemoryStatus(&memInfo);
        slobodno = memInfo.dwAvailVirtual/1024./1024.;
        printf("%g MB\n",slobodno);

        if (strcmp(ime,".")==0)
           {free(ime);free(imena[br]);break;}
        imena[br++]=ime;
        imena=(char**) realloc(imena,sizeof(char*)*(br+1));
    }

    for (i=0;i<br-1;i++)
        for (j=i+1;j<br;j++)
            if (strcmp(imena[i],imena[j])>0)
            {
                temp=imena[i];
                imena[i]=imena[j];
                imena[j]=temp;
            }


    //ovde ide sortiranje
    for (i=0;i<br;i++)
        printf("%s\n",imena[i]);

    for(i=0;i<br;i++)
       free(imena[i]);

    free(imena);

    return 0;
}

注意:教授添加了打印可用内存的行,因此我们可以看到realloc() 不起作用。我们输入的每个新字符串只占用sizeof(char)+4000000 字节并且不能重新分配。我试图找出原因。提前致谢

【问题讨论】:

  • 还有拜托,不要把可怜的malloc()friggin'返回值!太丑了,我的编译器会吐出汇编...
  • 代码似乎没有任何错误。我输入123&lt;cr&gt;qwe&lt;cr&gt;.&lt;cr&gt; 并得到123&lt;cr&gt;&lt;lf&gt;qwe&lt;cr&gt;&lt;lf&gt;
  • 忘了说内存消耗适中,我在 Linux 上测试。
  • 感谢您抽出宝贵时间发表评论。当我尝试输入“。”作为第一个输入,它只打印出我输入的字符串的长度(在本例中为 1)并停止程序。

标签: c malloc realloc


【解决方案1】:

我感觉它与 Windows 上的页面大小有关。 比如把4000000改成400000,就可以看到内存可以复用了。

我认为分配 4000000 会迫使 Windows 使用“巨大的”页面大小(4MB),并且由于某些(我不知道的)原因,realloc 不能以您期望的方式对它们起作用(即,使未使用的内存可用于其他分配)。

这似乎与 Realloc() does not correctly free memory in Windows 有关,其中提到了 VirutalAlloc,但我不确定它是否阐明了 realloc 不起作用的确切原因。

【讨论】:

  • 再一次我不能“投票”,因为我是新手,但我肯定会。这完全回答了我的问题,你甚至提供了一个类似问题的链接,我非常感激。既然我有一个起点,我会尝试寻找更多信息。非常感谢!
  • @alk 基本上 C 标准库在 Windows 上被破坏了。
【解决方案2】:

来自MSDN

memblock 参数指向内存块的开头。如果memblockNULL,则realloc 的行为方式与malloc 相同,并分配一个新的size 字节块。

所以ime=(char*) realloc(NULL,sizeof(char)*4000000); 这行每次只是malloc 的新内存。

【讨论】:

  • 是的,我想看看这是否有帮助。原来是 malloc(sizeof(char)*4000000);,我觉得是一样的,问题出在下一个 realloc,因为那行不通。
【解决方案3】:

realloc 不会释放内存。这些函数使用一大块内存(称为“堆”)并在您调用 realloc/malloc/calloc 时切出块。如果您需要的内存多于当前堆中的内存,则通过向操作系统请求更多内存来扩展堆。

当您调用realloc 来缩小内存块时,所发生的一切就是您不再需要的内存可供*alloc 在不同请求下再次分配。 reallocfree 都不会收缩堆以将内存返回给操作系统。 (如果你需要这样,你需要调用操作系统的本地内存分配过程,例如 Windows 上的VirtualAlloc。)

【讨论】:

  • 谢谢你的回答,我想我理解你了。 realloc 并没有真正释放内存,它只是使其可用于更多分配?
  • @alk - 不,这不是 Windows 专业。较新的 UNIX/Linux 实现可能会将内存返回给操作系统(我不知道;没有可玩的),但在较旧的实现中,行为是相同的 - *alloc 库管理自己的堆,调用break(2) 来获得更多的操作系统内存,使用 break() 来释放/分配内存是不可能的或性能不佳。
【解决方案4】:

问题不在于 realloc 不知道原始块的大小。即使我们的程序员无法获得这些信息,但它必须可供 realloc 使用(即使该块是使用 malloc 或 calloc 分配的)。

线

ime=(char*) realloc(ime,strlen(ime)+1);

看起来它正在缩小先前分配的块以完全适合内容,但实际上并没有要求缩小内存块并使剩余部分再次可用于新的分配。

编辑

我刚刚想到的另一件事:使用 realloc 进行收缩可能工作正常,但是运行时库不会将内存返回给操作系统,因为库会保留它以备下次分配。 只是,下一次分配是针对如此大的块,以至于它不适合用 realloc 释放的内存。

【讨论】:

  • 我想对此“投票”,但因为我刚加入,所以我不能。我认为您的答案很接近,问题是,教授说“让我们为字符串分配太多内存,然后切断未与 realloc 一起使用的内存。这不是它的工作原理吗?
  • @user1807181:这就是 realloc 在概念上的工作方式。实际上,使用 realloc 缩小内存块可能无济于事。
猜你喜欢
  • 2016-04-18
  • 2015-02-23
  • 2012-08-17
  • 2015-03-07
  • 1970-01-01
  • 2015-07-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多