首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何和何时为WinForms控件释放字体

如何和何时为WinForms控件释放字体
EN

Stack Overflow用户
提问于 2014-02-14 02:47:12
回答 2查看 3.6K关注 0票数 3

一个静态代码分析工具(来自HP的Fortify)抱怨在分配任何控件的Font属性时生成的WinForms代码。分析工具抱怨:

代码语言:javascript
运行
复制
line 143: this.mCopyrightLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));

在第143行中,InitializeComponent()函数在AboutWindowForm.cs中无法正确地释放由Font()分配的非托管系统资源。 解释: 程序无法正确释放使用非托管系统资源的托管对象。未能正确处置使用非托管系统资源的托管对象至少有两个常见原因:

  • 错误条件和其他特殊情况。
  • 程序的哪个部分负责释放资源的混乱。

在这种情况下,在第143行的AboutWindowForm.cs中分配的资源没有被正确地释放到程序路径上。

托管.NET对象的一小部分使用非托管系统资源。.NET的垃圾收集器可能无法以可预测的方式释放原始托管对象。因此,应用程序可能会耗尽可用内存,因为垃圾收集器不知道非托管资源占用的内存。大多数非托管资源泄漏问题都会导致一般的软件可靠性问题,但如果攻击者可以故意触发非托管资源泄漏,则攻击者可能会通过耗尽非托管资源池来发起拒绝服务攻击。

关于在windows窗体中处理字体的主题,我已经搜索了一段时间,以下是我收集到的要点:

  1. 创建字体将占用GDI对象,它是一个非托管资源,因此在不再需要时释放是非常重要的。
  2. 由于GDI对象昂贵且稀缺,因此WinForm缓存它们。
  3. Dispose WinForms控件还将释放其所有子控件并“释放所获得的非托管资源”。
  4. 如果窗体是无模式的,则在关闭时将处理该窗体。

因此,我想得出这样的结论:没有必要在VS生成的代码中显式地释放分配给控件的字体,而且可能我们不应该这样做,因为字体是缓存的?

我创建了一个非常简单的表单测试程序:通过单击一个按钮,我创建了一个使用不同字体的新空表单。在关闭新打开的表单后,Task中的GDI对象计数将立即下降。这就是上述几点的证据,不是吗?

然而,静态分析器似乎并不这么认为。它相信字体最终将由GC发布。它还认为这对非托管资源是不好的,因为占用的内存位于GC知识之外,因此GC不会被及时触发,因为GC没有感到内存压力。这使攻击者有机会故意触发耗尽非托管池。

你能帮我理解一下分析器的解释吗?它对WinFroms有效吗?手动处理创建的每个字体都很繁琐。

准确地说:

字体是在处理控件时立即显式地释放,还是Control释放对字体的引用并让GC处理所有左边的?

谢谢!

对我的问题的进一步更新:我做的另一个实验是:我在TaskManager和内存分析器中监视了我的测试TaskManager应用程序。主窗体有一个按钮,该按钮将打开另一个窗体,其字体在单击时是不同的。我注意到,当我单击按钮并打开新表单时,TaskManager中的GDI对象计数会上升。所以内存分析器所观察到的字体对象的计数。

但是,当我关闭新表单时,TaskManager中的GDI对象的计数立即下降。内存分析器中字体对象的计数没有改变,这意味着GC没有发生。然而,这些字体对象在内存分析器中被标记为“已处理但未收集”。

它让我感觉到,当窗体关闭时,设置为WinForms控件的字体属性的Font对象已经被正确地释放了。这场戏背后的逻辑似乎是

  1. 当窗体被关闭时,WinForm会处理它(显式地,而不是由GC)
  2. 释放窗体将递归地释放它的所有子控件。
  3. 释放控件将释放与其Font属性关联的Font对象(同样,显式地,而不是由GC)

但这只是间接证据+我的分析。我没有任何直接的证据,如源代码或官方文件支持它。

EN

回答 2

Stack Overflow用户

发布于 2014-02-14 05:54:13

您可以通过包含在使用构造模式中来控制字体的处理。在调用main中,应该将Application封装在表单的using结构中。

示例:

代码语言:javascript
运行
复制
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new FrmMainUtility());

对此:

代码语言:javascript
运行
复制
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        using (FrmMainUtility form = new FrmMainUtility())
        {
            Application.Run(form);
        }

试试看!

票数 0
EN

Stack Overflow用户

发布于 2016-06-24 08:09:49

当窗体关闭时,GC将自动释放不需要显式处理字体。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21769908

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档