代码之家  ›  专栏  ›  技术社区  ›  SmacL

物理内存量随着空闲块的增加而增加

  •  1
  • SmacL  · 技术社区  · 15 年前

    我有一块C++代码,它可以按如下方式释放内存

    for (int i = Pages-1; i >= NewPages; i--)
    {
        LPVOID p = m_Pages[i];
        free(p);
    }
    

    虽然代码可以正常工作,但当从异常处理程序调用时,它的运行速度非常慢。在单步执行上述循环的同时查看任务管理器,进程使用的物理内存量(Mem Usage)随着每次调用free而增加,而虚拟内存(VM Size)保持不变。最终这个过程异常终止。

    for (int i = Pages; i < NewPages; i++)
    {
        LPVOID p = malloc(m_ElementsPerPage*m_ElementSize);
        if (!p)
            AfxThrowMemoryException( );
        m_Pages.Add(p);
    }
    

    编辑:

    编辑2: 更完整的代码版本如下:;

    void  MyArray::ResizeArray(int NewPages)
    {
        int Pages = m_Pages.GetSize();
        if (NewPages != Pages)
        {
            if (NewPages > Pages)   // Grow the page array
            {
                for (int i = Pages; i < NewPages; i++)
                {
                    LPVOID p = malloc(m_ElementsPerPage*m_ElementSize);
                    if (!p)
                        AfxThrowMemoryException( );
                    m_Pages.Add(p);
                }
            } else  // Shrink the page array
            {
                for (int i = Pages-1; i >= NewPages; i--)
                {
                    LPVOID p = m_Pages[i];
                        free(p);
                }
                m_Pages.SetSize(NewPages);
            }
        }
    }
    
    2 回复  |  直到 15 年前
        1
  •  1
  •   plodoc    15 年前

    您的进程可以使用2兆字节的内存。当malloc失败时,使用的内存将接近该值。如果您的计算机的物理内存较少,则该进程的许多内存页将被分页到磁盘。

    当异常处理程序释放回内存时,堆管理器将触及所有页,将它们带回物理内存。这会很慢。

        2
  •  3
  •   sth    15 年前

    你的分配循环从 Pages 高达 NewPages Pages-1 新页 . 只有一个是正确的,这取决于 Pages <= NewPages 不管怎样。

    除此之外,打电话 free() 不一定会减少程序的内存大小。这取决于 malloc() 免费() . 如果在同一内存页上还有其他分配的内存块,那么 不能 把页面还给操作系统。

    如果malloc实现在分配的块旁边存储了一些管理信息(例如块有多大),那么使用的物理内存可能会增加,因为释放的内存需要交换进来。Free需要读取/修改这些管理信息来完成它的工作,为此需要首先交换内存。