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

Windows平台下C程序进程内存使用相关技术问题咨询

C程序内存监控问题解答

示例代码

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

void getMemInfo(){
    PROCESS_MEMORY_COUNTERS_EX pmc;
    GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS *)&pmc, sizeof(pmc));
    SIZE_T virtualMemUsedByMe = pmc.PrivateUsage;
    SIZE_T physMemUsedByMe = pmc.WorkingSetSize;
    printf("%ld, %ld\n", virtualMemUsedByMe, physMemUsedByMe);
}
int main()
{
    double a[1000];
    
    getMemInfo();
    double *b = malloc(sizeof(double)*1000);
    
    getMemInfo();
    free(b);

    getMemInfo();
    return 0;
}

问题解答

1. 为何每次运行内存输出有差异?是否误用pmc参数?

没有误用参数,PrivateUsage(私有虚拟内存)和WorkingSetSize(物理驻留内存)的用法是正确的。每次运行结果不同是因为Windows进程的内存环境本身就不是完全固定的:

  • 进程启动时,系统加载依赖DLL的时机、内存碎片状态、CRT(C运行时库)初始化的额外开销都会有细微差异
  • 系统的内存管理机制会动态调整进程的内存分配,比如物理内存不足时会把部分内存换出到分页文件,导致WorkingSetSize波动
  • 即使是相同的代码,不同运行实例的栈、堆初始化位置也可能不同,带来内存统计的细微差别

2. 如何及时记录内存分配前后的使用情况?

  • 紧挨着调用监控函数:确保getMemInfo()直接写在malloc/free的前后,中间不要插入其他可能触发内存分配的操作(比如额外的printf、系统调用等),避免干扰统计结果
  • 封装宏或包装函数:可以把内存监控和分配操作绑定,减少手动调用的失误,比如:
#define MALLOC_AND_RECORD(size) ({ \
    getMemInfo(); \
    void* ptr = malloc(size); \
    getMemInfo(); \
    ptr; \
})

#define FREE_AND_RECORD(ptr) ({ \
    getMemInfo(); \
    free(ptr); \
    getMemInfo(); \
})

或者封装自定义的malloc/free:

void* tracked_malloc(size_t size) {
    getMemInfo();
    void* res = malloc(size);
    getMemInfo();
    return res;
}

void tracked_free(void* ptr) {
    getMemInfo();
    free(ptr);
    getMemInfo();
}
  • 注意编译模式差异:调试版CRT会给malloc分配的内存加上额外的调试信息(比如边界检查、内存块标记),导致内存统计数值比Release版大,测试时要保持编译模式一致

3. 优化C项目时,应选用哪个pmc参数作为性能基准?

要根据你的优化目标来选:

  • 优化物理内存占用(比如低内存设备、服务器场景):选WorkingSetSize,它代表当前进程实际占用的物理内存。但注意这个值会被系统的内存置换机制影响,建议多次采样取稳定后的平均值
  • 优化虚拟内存占用(比如32位程序避免地址空间耗尽):选PrivateUsage,它统计的是进程独占的虚拟内存,不包含共享的DLL、系统内存等,能准确反映进程自身的内存开销
  • 排查内存泄漏:优先看PrivateUsage,因为泄漏的内存会持续占用私有虚拟内存,而WorkingSetSize可能被系统换出,无法准确体现泄漏情况
  • 补充:如果需要更精准的堆内存统计,建议用CRT自带的内存跟踪函数(比如_CrtMemCheckpoint、_heapwalk),因为GetProcessMemoryInfo统计的是整个进程的内存,包括栈、DLL、内核对象等,无法区分堆内存的具体使用情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 13:32:39