The Truth About GCHandles
I've heard several people asking why GCHandle doesn't implement IDisposable, considering it wraps an unmanaged resource (a handle) and needs to be explicitly freed (using GCHandle.Free()). Before I explain the reason, I want to give a little background on GCHandles and their dangers.
What's a GCHandle?
A GCHandle is a struct that contains a handle to an object. It's mainly used for holding onto a managed object that gets passed to the unmanaged world to prevent the GC from collecting the object. You can also create a Pinned GCHandle to a managed object and retrieve the object's address in memory.
How are GCHandles dangerous?
When you create a new GCHandle, a new entry in the AppDomain's handle table is created. This entry is kept until the handle is freed (via GCHandle.Free()) or the AppDomain is unloaded.
Things get tricky if you were to make a copy of a GCHandle:
Object obj = new Object();
GCHandle gch = GCHandle.Alloc(obj, GCHandleType.Normal);
GCHandle gch2 = gch;
Since
GCHandle is value type, gch2 has its own copy of the handle. You now
have two handles that point to the same entry in the handle table.
Unfortunately, since gch2 is a copy of –not a reference to– gch,
anything that happens to gch doesn't happen to gch2. For example,
calling gch.Free() will delete the entry from the handle table, but not
update gch2, so gch2.IsAllocated will return true, but gch2.Target will
be null. The same problem arises with casting to and from IntPtrs, and
when GCHandles get boxed. Unlike double-freeing a single GCHandle,
freeing the copy will NOT throw an InvalidOperationException. You have
to be very careful not to double-Free your handles since this can
corrupt the handle table.
Why don't GCHandles implement IDisposable?
One
of the main purposes of IDisposable to avoid the use of finalizers.
This is because finalizers are not run deterministically, and result in
promoting a finalizable object a generation, effectively keeping in
memory longer. Since GCHandle is a value type, it has no finalizer, and
is not collected by the GC, so these problems are eliminated. Another
other main use of IDisposable is to clean up unmanaged resources as soon
as you are done with them. With a GCHandle, the resource is the handle
which is cleaned up by calling GCHandle.Free(). If Free isn't called,
the handle gets cleaned up when the appdomain is unloaded.
One
of the side effects of having a struct implement IDisposable, is that
users may be tempted to cast their GCHandles as IDisposable, which boxes
the GCHandle into an IDisposable object on the heap, and the two
GCHandles get out-of-sync. The same problem arises with the putting a
disposable struct into a using block:
struct Test : IDisposable
{
public bool disposed; // initialized to false
public void Dispose()
{
disposed = true;
}
}
public void Foo()
{
Test t = new Test();
using (t)
{
// do stuff
}
if (!t.disposed)
{
t.Dispose();
}
}
t.disposed
will return false, since it was a copy of t whose Dispose method was
called. If t were a GCHandle, then the handle would be removed from the
appdomain's handle table, and calling Free after the using would result
in a double Free, even though IsAllocated would return true!
Remember,
GCHandles are advanced structures, and one should be very careful to
ensure they are cleaned up properly. Unfortunately, IDisposable makes it
easy to get this wrong, so the BCL designers erred on the side of
caution, and gave GCHandle a Free() method to use.
The Truth About GCHandles的更多相关文章
- hdu3729 I'm Telling the Truth (二分图的最大匹配)
http://acm.hdu.edu.cn/showproblem.php?pid=3729 I'm Telling the Truth Time Limit: 2000/1000 MS (Java/ ...
- windbg 命令 gchandles
使用windbg导出dump文件 .dump /ma D:\testdump.dmp gchandles命令列出句柄,同时列出句柄引用的对象,演示代码如下: using System; using S ...
- I'm Telling the Truth(二分图)
.I'm Telling the Truth Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- 论文笔记之:Playing for Data: Ground Truth from Computer Games
Playing for Data: Ground Truth from Computer Games ECCV 2016 Project Page:http://download.visinf.tu- ...
- codeforces Gym 100187L L. Ministry of Truth 水题
L. Ministry of Truth Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/p ...
- Codeforces Gym 100610 Problem H. Horrible Truth 瞎搞
Problem H. Horrible Truth Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/1006 ...
- 关于warning: suggest parentheses around assignment used as truth value [-Wparentheses]|的解决方法
今天,在调试的时候一直出现warning: suggest parentheses around assignment used as truth value 代码如下: if(startTime== ...
- Pretty Smart? Why We Equate Beauty With Truth
Pretty Smart? Why We Equate Beauty With Truth With some regularity we hear about the latest beauty-p ...
- [usaco]2013-jan Liars and Truth Tellers 真假奶牛
Description 约翰有N头奶牛,有一部分奶牛是真话奶牛,它们只说真话,而剩下的是假话奶牛,只说假话.有一天,约翰从奶牛的闲谈中陆续得到了M句话,第i句话出自第Xi头奶牛,它会告诉约翰第Yi头是 ...
随机推荐
- 九度OJ 1144:Freckles(斑点) (最小生成树)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1538 解决:760 题目描述: In an episode of the Dick Van Dyke show, little Richi ...
- 九度OJ 1038:Sum of Factorials(阶乘的和) (DP、递归)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1845 解决:780 题目描述: John von Neumann, b. Dec. 28, 1903, d. Feb. 8, 1957, ...
- 销售订单增强字段 bapi更新
如果增强字段在销售订单抬头(vbak)上,则要将增强字段一并append到如下四个表/结构中: VBAKKOZ VBAKKOZX BAPE_VBAK BAPE_VBAKX 在行项目(vbap)上: V ...
- ios点击链接直接跳转到 App Store 指定应用下载页面
//跳转到应用页面 NSString *str = [NSString stringWithFormat:@"http://itunes.apple.com/us/app/id%d&quo ...
- 解决ubuntu12.04下安装gitlabError Compiling CSS asset的错误以及401资源错误
安装过程 https://www.gitlab.com.cn/installation/#ubuntu 解决过程 12.04ubuntu坑太多 解决有用的链接如下 https://blog.csdn. ...
- 关于connect: network is unreachable 问题的解决【转】
本文转载自:https://blog.csdn.net/liukun321/article/details/6662950 由于发现原创文章,在未署名作者及出处的情况下被转载.在以后所有的原创文章开头 ...
- ubuntn14.04 使用 nvm创建多版本node环境
1. 下载 nvm wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.32.1/install.sh | bash 2. 然后 ...
- 基于KD-Tree的最近邻搜索
目标:查询目标点附近的10个最近邻邻居. load fisheriris x = meas(:,:); figure(); g1=gscatter(x(:,),x(:,),species); %spe ...
- BZOJ 1208 [HNOI2004]宠物收养所:Splay(伸展树)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1208 题意: 有一个宠物收养所,在接下来一段时间内会陆续有一些宠物进到店里,或是一些人来领 ...
- HDU 2035 人见人爱A^B(二分求幂,快速求幂)
题意:求A的B次方的后三位数字 思路1:常规求幂,直接取余求解 代码: #include<iostream> #include<cstdio> using namespace ...