Icon.FromHandle(handler) 小心GDI泄露导致Crash

本文通过实例探讨.NET程序中GDI资源泄露问题。作者通过一个具体案例,详细介绍了如何定位和解决由Bitmap和Icon对象引起的GDI资源泄露,并提供了有效的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

来源:Anders06  CNBlogs

写此文目的在于备份,以供日后查阅。

GDI泄露这玩意儿以前压根没听过, 第一次了解到这东西存在是在很久很久以前在我们的项目中真实遇到过了,当时的情况是这样的一同事发现狂点菜单某一选项几分钟,程序就会crash,而且每次都能重现,起初猜测是资源泄露,后来打开任务管理器监视GDI Object一栏发现每点一次菜单,GDI Object的数量就飙涨,差不多到10000的时候程序就会crash。当时很佩服那同事咋能发现那Bug,也惊奇任务管理器竟然能监视那么多的资源利用。

最后发现栽在于创建Bitmap却忘记释放,好像跟Handler有关(嗯,忘了O(∩_∩)O哈哈~)

最近发现如下代码,直觉告诉我这里也应该有GDI泄露问题。

ContractedBlock.gif ExpandedBlockStart.gif Create Icon From Bitmap
 1public static System.Drawing.Icon FromBitmapToIcon(System.Drawing.Bitmap bitmap)
 2ExpandedBlockStart.gifContractedBlock.gif{
 3    if (null == bitmap)
 4        return null;
 5    IntPtr handler = bitmap.GetHicon();
 6    if (null != handler)
 7ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 8        System.Drawing.Icon result = System.Drawing.Icon.FromHandle(handler);
 9        return result;
10    }

11    return null;
12}

13

写个测试程序,发现每调用一次FromBitmapToIcon()方法,GDI Object的数量就+3,如果点击如下测试程序中的Button超过10次,程序就会crash(GDI Object的数量 达到了9999上线)。

ContractedBlock.gif ExpandedBlockStart.gif Test Code
1private void button1_Click(object sender, EventArgs e)
2ExpandedBlockStart.gifContractedBlock.gif{
3    for (int i = 0; i < 333; i++)
4ExpandedSubBlockStart.gifContractedSubBlock.gif    {
5        Icon icon = FromBitmapToIcon(Properties.Resources.Background);
6        icon.Dispose();
7    }

8}

9

 

GDILeak

捕捉到的异常如下:

image 

解决的方法是,创建了Icon对象后调用如下方法释放Handler:

[DllImport("user32.dll")]

public static extern bool DestroyIcon(IntPtr handle);

还有个用来释放对象的方法为:

[DllImport("gdi32.dll")]

public static extern bool DeleteObject(IntPtr hObject);

 

句柄这玩意儿不懂,有大大指教不(*^__^*) 

 

Google后发现如下两篇文章,解释的很清楚了,供参阅:

 

(PS. 正如先前已有很多同学写过这方面的文章,但要不是自己亲自遇到了,还真的不会在意这个问题。虽说本文只是用于收藏,只是作为一个知识点,仅供日后翻阅,这篇文章也没什么技术含量, 但还是想放在首页一下下,毕竟这个东西要是没接触过,突然横空遇到这样莫名crash的问题,可能也会一时无从下手。希望对大家有用。本人脸薄,如有人觉得不妥支一下,定然撤下。

我就硬头皮上一次了 ~\(≧▽≦)/~啦啦啦)

转载于:https://www.cnblogs.com/anders06/archive/2009/01/22/1380001.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值