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

未托管内存未在任务管理器显示的原因及测试方法咨询

为什么任务管理器看不到Marshal.AllocHGlobal分配的100MB内存?

这其实是Windows虚拟内存系统的懒加载(lazy commitment)机制在起作用。当你调用Marshal.AllocHGlobal(100000000)时,操作系统只是为你的进程预留了100MB的虚拟地址空间,但并没有真正将物理内存(或页面文件中的空间)分配给它。只有当你实际写入或读取这块内存中的内容时,Windows才会触发“提交”操作,把真正的内存页分配给进程,这时候任务管理器里的内存占用才会体现出来。

你的代码里只是分配了地址空间,没有对这块内存做任何读写操作,所以任务管理器显示的是进程当前实际提交的内存,自然看不到这100MB的变化。

测试非托管堆内存消耗的方法

如果想验证非托管内存的分配情况,你可以试试这些方法:

1. 触发内存实际提交

修改你的代码,对分配的内存进行一次写入操作,强制Windows提交内存页:

IntPtr x = Marshal.AllocHGlobal(100000000);
// 写入第一个字节,触发内存提交
Marshal.WriteByte(x, 0, 0);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
Marshal.FreeHGlobal(x);
Console.ReadKey(true);

这时候再看任务管理器,就能看到进程的内存占用明显上升了。

2. 使用.NET的Process类获取精确内存数据

你可以通过System.Diagnostics.Process类直接读取进程的内存统计信息,这些数据比任务管理器更精准,能直接反映非托管内存的提交情况:

using System.Diagnostics;

// ...

IntPtr x = Marshal.AllocHGlobal(100000000);
Marshal.WriteByte(x, 0, 0); // 触发提交
var process = Process.GetCurrentProcess();
// PrivateMemorySize64 表示进程的私有提交内存(包括非托管堆)
Console.WriteLine($"私有提交内存: {process.PrivateMemorySize64 / 1024 / 1024} MB");
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
Marshal.FreeHGlobal(x);
Console.WriteLine($"释放后私有提交内存: {process.PrivateMemorySize64 / 1024 / 1024} MB");
Console.ReadKey(true);

3. 使用专业内存分析工具

  • Visual Studio 诊断工具:打开你的项目后,点击“调试”→“显示诊断工具”,选择“内存使用”选项。它可以清晰区分托管堆和非托管堆的内存占用,还能追踪非托管内存的分配点。
  • WinDbg:这是Windows官方的调试工具,使用!heap命令可以查看非托管堆的详细信息,比如已分配块的大小、数量,甚至能定位到具体的分配调用栈。
  • Process Explorer:比任务管理器更强大的进程查看工具,它能显示进程的虚拟内存、提交内存、工作集等多个维度的内存数据,还能查看进程的堆信息。

4. 自定义内存跟踪封装

如果是在自己的项目中持续监控非托管内存,你可以封装AllocHGlobal和FreeHGlobal,维护一个全局计数器:

public static class UnmanagedMemoryTracker
{
    private static long _allocatedBytes = 0;
    private static readonly object _lock = new object();
    private static readonly Dictionary<IntPtr, long> _pointerSizes = new Dictionary<IntPtr, long>();

    public static long CurrentAllocatedBytes
    {
        get { lock (_lock) return _allocatedBytes; }
    }

    public static IntPtr AllocHGlobal(long cb)
    {
        var ptr = Marshal.AllocHGlobal((int)cb);
        lock (_lock)
        {
            _allocatedBytes += cb;
            _pointerSizes[ptr] = cb;
        }
        return ptr;
    }

    public static void FreeHGlobal(IntPtr hglobal)
    {
        lock (_lock)
        {
            if (_pointerSizes.TryGetValue(hglobal, out long size))
            {
                _allocatedBytes -= size;
                _pointerSizes.Remove(hglobal);
            }
        }
        Marshal.FreeHGlobal(hglobal);
    }
}

这样你就可以在代码的任何地方通过UnmanagedMemoryTracker.CurrentAllocatedBytes查看当前非托管内存的总占用量,适合自定义的测试和监控场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:21:00