You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C程序中malloc分配内存后,系统可用内存为何未明显下降?

为何内存分配程序未按预期消耗物理内存?

我想要编写一个每秒分配一段内存的C程序,模拟内存不足(OOM)场景(故意不释放内存),并输出剩余可用内存。以下是Linux平台的程序代码:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

int main() {
    size_t mbs = 500 * 1000000; // 500mb

    while(true) {
        sleep(1);

        void* tmp = malloc(mbs);

        system("free");
    }
    
    return 0;
}

调用system执行free命令查看可用内存,我预期可用内存每秒减少500MB,但实际约32GB内存中可用内存始终维持在25GB左右,尝试10MB、100MB分配量结果一致。Windows平台类似程序也出现相同现象:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

int main() {
    size_t mbs = 500 * 1000000; // 500mb

    while(true) {
        Sleep(2);

        void* tmp = malloc(mbs);

        system("systeminfo |find \"Available Physical Memory\"");
    }
    
    return 0;
}

为何未观察到内存消耗的下降?


核心原因:虚拟内存与写时复制机制

你的程序仅调用malloc(Windows底层对应HeapAlloc),但并未对分配的内存块执行实际写入操作。现代操作系统采用虚拟内存管理和**写时复制(Copy-On-Write, COW)**机制:

  • malloc只是向操作系统申请了虚拟地址空间,内核不会立即分配实际物理内存;
  • 只有当进程首次向该虚拟地址空间写入数据时,内核才会真正分配物理页帧并完成映射。

free(Linux)或systeminfo(Windows)显示的是已占用的物理内存,而非进程持有的虚拟内存空间,因此你无法观察到预期的内存消耗下降。

解决方法:触发物理内存分配

要让系统真正分配物理内存,需对malloc返回的指针指向的内存执行写入操作,例如用memset填充整个内存块:

Linux 修改后代码

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int main() {
    size_t mbs = 500 * 1000000; // 500mb

    while(1) {
        sleep(1);

        void* tmp = malloc(mbs);
        if (tmp == NULL) {
            perror("malloc failed");
            break;
        }
        // 写入内存触发物理页分配
        memset(tmp, 0, mbs);

        system("free");
    }
    
    return 0;
}

Windows 修改后代码

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <string.h>

int main() {
    size_t mbs = 500 * 1000000; // 500mb

    while(1) {
        Sleep(2);

        void* tmp = malloc(mbs);
        if (tmp == NULL) {
            printf("malloc failed\n");
            break;
        }
        // 写入内存触发物理页分配
        memset(tmp, 0, mbs);

        system("systeminfo |find \"Available Physical Memory\"");
    }
    
    return 0;
}

额外说明

  • 务必添加内存分配失败判断:当物理内存耗尽时,malloc会返回NULL,此时终止循环避免无效申请;
  • Linux下可通过top或ps aux查看进程的虚拟内存(VSZ)和物理内存(RSS),RSS会随写入操作增长;Windows下可在任务管理器查看进程的「工作集(Working Set)」。

内容的提问来源于stack exchange,提问作者TheMemeMachine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 21:07:05