当我使用 List 时,我在 Jetbrains dotMemory 中看到的“固定句柄对象[]”是什么?

2024-02-25

我试图想出最简单的代码来重现我所看到的内容。完整的程序如下,但我将在这里描述它。假设我有一个名为ListData它只是有一些属性。那么假设我有一个MyList有成员的类List<ListData> m_list。认为m_list被初始化在MyList构造函数。

在主要方法中我只是创建其中之一MyList对象,添加一些ListData到它,然后让它超出范围。我在 dotMemory 后拍摄快照ListData已添加,然后我在添加后拍摄另一张快照MyList对象超出范围。

在 dotMemory 中我可以看到MyList对象已按预期被回收。我也看到了两个ListData我创建的对象也按预期被回收。

What I do not understand is why is there a ListData[] that survived? Here is a screen shot of this: Screenshot of this in dotMemory

我在最新快照上打开幸存的对象ListData[]然后我查看关键保留路径,这就是我看到的。

我是 .NET 内存管理的新手,我创建了这个示例应用程序来帮助我探索它。我下载了 JetBrains dotMemory 4.3 版的试用版。我使用的是 Visual Studio 2013 专业版。我必须学习内存管理,这样我才能解决工作中遇到的内存问题。

这是可用于重现此内容的完整程序。这只是一个快速而肮脏的应用程序,但如果你分析它,它就会得到我要问的东西。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{

    class ListData
    {
        public ListData(string name, int n) { Name = name; Num = n; }
        public string Name { get; private set; }
        public int Num { get; private set; }
    }

    class MyList
    {

        public MyList()
        {
            m = new List<ListData>();
        }

        public void AddString(ListData d)
        {
            m.Add(d);
        }

        private List<ListData> m;

    }


    class Program
    {
        static void Main(string[] args)
        {
            {
                MyList l = new MyList();
                bool bRunning = true;
                while (bRunning)
                {
                    Console.WriteLine("a or q");
                    string input = Console.ReadLine();
                    switch (input)
                    {
                        case "a":
                            {
                                Console.WriteLine("Name: ");
                                string strName = Console.ReadLine();
                                Console.WriteLine("Num: ");
                                string strNum = Console.ReadLine();
                                l.AddString(new ListData(strName, Convert.ToInt32(strNum)));
                                break;
                            }
                        case "q":
                            {
                                bRunning = false;
                                break;
                            }
                    }
                }
            }

            Console.WriteLine("good bye");
            Console.ReadLine();
        }
    }
}

Steps:

  1. 在发布中构建上述代码。
  2. 在 dotMemory 中,选择分析 独立应用程序。
  3. 浏览到发行版 exe。
  4. 选择立即开始收集分配数据的选项。
  5. 单击运行。
  6. 立即拍摄快照并将其命名为“before”。这是在任何之前 添加了列表数据。
  7. 在应用程序中,键入 a 并添加两个 ListData。
  8. 在 dotMemory 中,拍摄另一个快照并将其命名为“added 2”,因为我们 添加了两个ListData。
  9. 在应用程序中,输入 q 退出(MyList 将超出范围)。在再次输入 Enter 退出应用程序之前,请在 dotMemory 中拍摄另一个快照。将其命名为“超出范围”。
  10. 在应用程序中,输入 Enter 以关闭应用程序。
  11. 在dotMemory中,比较“添加的2”和“超出范围” 快照。按名称空间分组。您将看到我所指的 ListData[]。

请注意,MyList 和两个 ListData 对象确实得到了垃圾回收,但 ListData[] 没有。为什么有一个 ListData[] 挂在周围?我怎样才能让它被垃圾收集?


为什么有一个 ListData[] 挂在周围?我怎样才能让它得到 垃圾收集了?

如果您查看 dotMemory 内的“创建堆栈跟踪”,您将看到:

这表明你空ListData[0]实例是通过静态构造函数创建的List<T>. 如果你看一下源码 http://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,61f6a8d9f0c40f6e,references,你会看到这个:

static readonly T[]  _emptyArray = new T[0];    

List<T>初始化默认的空数组以优化避免每次创建新数组时进行此类分配List<T>。这是默认构造函数:

public List() 
{
    _items = _emptyArray;
}

只有您使用的一个List<T>.Add,它会调整数组的大小吗?

static成员引用自《高频堆》 https://stackoverflow.com/questions/4405627/high-frequency-heap,为每个创建一次AppDomain在您的应用程序中。固定的object[]你看到的实际上是所有的位置static实例被存储。

由于实例是static,它将在应用程序的整个生命周期中保留在内存中。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当我使用 List 时,我在 Jetbrains dotMemory 中看到的“固定句柄对象[]”是什么? 的相关文章

  • Blazor 与 Razor

    随着 Blazor 的发明 我想知道这两种语言之间是否存在显着的效率 无论是在代码创建方面还是在代码的实际编译 执行方面 https github com SteveSanderson Blazor https github com Ste
  • 通信对象 System.ServiceModel.Channels.ServiceChannel 不能用于通信

    通信对象System ServiceModel Channels ServiceChannel 无法用于通信 因为它处于故障状态 这个错误到底是什么意思 我该如何解决它 您收到此错误是因为您让服务器端发生 NET 异常 并且您没有捕获并处理
  • 在 C++11 中省略返回类型

    我最近发现自己在 C 11 模式下的 gcc 4 5 中使用了以下宏 define RETURN x gt decltype x return x 并编写这样的函数 template
  • 有什么工具可以说明每种方法运行需要多长时间?

    我的程序的某些部分速度很慢 我想知道是否有我可以使用的工具 例如它可以告诉我可以运行 methodA 花了 100ms 等等 或者类似的有用信息 如果您使用的是 Visual Studio Team System 性能工具 中有一个内置分析
  • 调试内存不足异常

    在修复我制作的小型 ASP NET C Web 应用程序的错误时 我遇到了 OutOfMemoryException 没有关于在哪里查看的提示 因为这是一个编译时错误 如何诊断此异常 我假设这正是内存分析发挥作用的地方 有小费吗 Thank
  • ZLIB 解压缩

    我编写了一个小型应用程序 该应用程序应该解压缩以 gzip deflate 格式编码的数据 为了实现这一点 我使用 ZLIB 库 使用解压缩功能 问题是这个功能不起作用 换句话说 数据不是未压缩的 我在这里发布代码 int decompre
  • 转到 C# WPF 中的第一页

    我正在 WPF 中使用导航服务 为了导航到页面 我使用 this NavigationService Navigate new MyPage 为了返回我使用 this NavigationService GoBack 但是如何在不使用的情况
  • 是否有与 C++11 emplace/emplace_back 函数类似的 C# 函数?

    从 C 11 开始 可以写类似的东西 include
  • 单元测试失败,异常代码为 c0000005

    我正在尝试使用本机单元测试项目在 Visual Studios 2012 中创建单元测试 这是我的测试 TEST METHOD CalculationsRoundTests int result Calculations Round 1 0
  • 事件日志写入错误

    很简单 我想向事件日志写入一些内容 protected override void OnStop TODO Add code here to perform any tear down necessary to stop your serv
  • 从 Orchard 内的主题渲染图像

    我刚刚选择 Orchard 来构建我的博客 作为创建这个新博客的努力的一部分 我正在创建一个自定义主题 这个自定义主题同时具有 CSS 和图像 我的问题 我的问题基本上可以归结为 如何渲染属于主题一部分的图像 到目前为止我已经尝试过的 我尝
  • 在 C 中复制两个相邻字节的最快方法是什么?

    好吧 让我们从最明显的解决方案开始 memcpy Ptr const char a b 2 调用库函数的开销相当大 编译器有时不会优化它 我不会依赖编译器优化 但即使 GCC 很聪明 如果我将程序移植到带有垃圾编译器的更奇特的平台上 我也不
  • 如何在 GCC 5 中处理双 ABI?

    我尝试了解如何克服 GCC 5 中引入的双重 ABI 的问题 但是 我没能做到 这是一个重现错误的非常简单的示例 我使用的GCC版本是5 2 如您所见 我的主要函数 在 main cpp 文件中 非常简单 main cpp include
  • .NET UI 元素线程限制的原因

    我们知道 除了实例化元素的线程之外 不可能从任何线程执行操作任何 UI 元素属性的代码 我的问题是 为什么 我记得当我们使用 COM 用户界面元素时 在 COM Visual Basic 6 0 时代 所有 UI 元素都是使用 COM 类和
  • 为什么 Ajax.BeginForm 在 Chrome 中不起作用?

    我正在使用 c NET MVC2 并尝试创建一个 ajax 表单来调用删除数据库记录 RemoveRelation 的方法 删除记录的过程正在按预期进行 删除记录后 表单应调用一个 JavaScript 函数 从视觉效果中删除该记录 Rem
  • 以编程方式使用自定义元素创建网格

    我正在尝试以编程方式创建一个网格 并将自定义控件作为子项附加到网格中 作为 2x2 矩阵中的第 0 行第 0 列 为了让事情变得更棘手 我使用了 MVVM 设计模式 下面是一些代码可以帮助大家理解这个想法 应用程序 xaml cs base
  • 在基类集合上调用派生方法

    我有一个名为 A 的抽象类 以及实现 A 的其他类 B C D E 我的派生类持有不同类型的值 我还有一个 A 对象的列表 abstract class A class B class A public int val get privat
  • Swagger 为 ASP.CORE 3 中的字典生成错误的 URL

    当从查询字符串中提取的模型将字典作为其属性之一时 Swagger 会生成不正确的 URL 如何告诉 Swagger 更改 URL 中字典的格式或手动定义输入参数模式而不自动生成 尝试使用 Swashbuckle 和 NSwag 控制器 pu
  • Azure函数版本2.0-应用程序blobTrigger不工作

    我有一个工作功能应用程序 它有一个 blob 输入和一个事件中心输出 在测试版中工作 随着最新的更改 我的功能不再起作用 我尝试根据发行说明更新 host json 文件 但它没有引用 blob 触发器 version 2 0 extens
  • 如何创建向后兼容 Windows 7 的缩放和尺寸更改每显示器 DPI 感知应用程序?

    我是 WPF 和 DPI 感知 API 的新手 正在编写一个在 Windows 7 8 1 和 10 中运行的应用程序 我使用具有不同每个显示器 DPI 设置的多个显示器 并且有兴趣将我的应用程序制作为跨桌面配置尽可能兼容 我已经知道可以将

随机推荐