windows - Realloc() 在 Windows 中没有正确释放内存

标签 windows memory realloc

我试图在 Windows 应用程序中使用 realloc()。我正在分配一大块内存,然后在知道正确的大小后使用 realloc() 将其缩小。

我发现虽然 realloc() 似乎工作正常(任务管理器中的内存反射(reflect)了您的预期),但应用程序最终会耗尽内存。据我所知,就好像 relloc() 释放了内存,但没有释放与内存关联的虚拟地址空间。结果,ma​​lloc() 最终会失败。

这是一个演示问题的小型控制台应用程序:

int _tmain(int argc, _TCHAR* argv[])
{
    static const DWORD dwAllocSize = (50 * 1024 * 1024);
    static const DWORD dwReallocSize = 10240;
    static const DWORD dwMaxIterations = 200;

    BYTE* arpMemory[dwMaxIterations];
    memset( arpMemory, 0, sizeof(arpMemory) );

    for( DWORD i = 0; i < dwMaxIterations; i++ )
    {
        arpMemory[i] = (BYTE*) malloc( dwAllocSize );
        if( !arpMemory[i] )
        {
            printf("OUT OF MEMORY after %d iterations!\n", i);
            return -1;
        }

        BYTE* pRealloc = (BYTE*) realloc( arpMemory[i], dwReallocSize );
        if( !pRealloc )
        {
            printf("Realloc FAILED after %d iterations!\n", i);
            return -1;
        }
        else if( pRealloc != arpMemory[i] )
        {
            printf("Warning: Pointer changed: 0x%08X -> 0x%08X\n", arpMemory[i], pRealloc);
            arpMemory[i] = pRealloc;
        }
    }

    printf("Success!\n");

    for( int i = 0; i < dwMaxIterations; i++ )
        free( arpMemory[i] );

    return 0;
}

该应用重复分配 50 MB 内存,然后立即将其大小调整为仅 10K。如果你运行它,你会发现它在仅仅 38 次迭代后就失败了,出现了 OUT OF MEMORY 错误。这对应于最初分配的 2GB 内存——这是 Windows 应用程序的地址空间限制。

有趣的是,如果您查看任务管理器,您会发现该应用程序几乎不占用内存。然而 ma​​lloc() 失败了。这就是让我相信虚拟地址空间正在耗尽的原因。

(另一个要尝试的实验是注释掉重新分配,因此没有内存被释放或重新分配。应用程序在完全相同的地方失败:38 次迭代后。唯一的区别是这次任务管理器反射(reflect)了完整的 2GB使用。)

最后一点信息:这个应用程序可以在 Linux 下运行。所以这个 realloc() 问题是严格的 Windows 独有的。

有什么想法吗?

最佳答案

这样做是在对堆进行碎片化。无论您使用 realloc() 释放什么,都会添加到空闲 block 列表中。永远不会被再次使用,因为你总是要求一个比它更大的新 block 。这些空闲 block 只会累积占用虚拟内存,直到不再剩下为止。当您一次丢弃近 50 兆字节时,发生的速度非常快。

您需要重新考虑您的方法。

关于windows - Realloc() 在 Windows 中没有正确释放内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9164837/

相关文章:

windows - 为什么在Win7 64bit下 'ntQuerySystemInformation'无法获取大于65535的进程id?

c++ - 编写自定义 GetModuleHandle 函数的原因是什么?

WriteFile() 函数可以停止工作吗?

c - gdb 报错,但程序运行正常

c - 重新分配无效的旧大小

python - subprocess:删除Windows中的子进程

R GPU工具: clearing or reusing memory

c# - 设置人工​​内存限制

objective-c - 正确使用FMDB/内存

c - 为什么在使用 realloc() 时出现段错误?