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.

时间: 2024-10-27 06:34:46

The Truth About GCHandles的相关文章

HDU - 3729 I'm Telling the Truth(二分匹配)

题意:有n个人,每个人给出自己的名次区间,问最多有多少个人没撒谎,如果有多解,输出字典序最大的解. 分析: 1.因为字典序最大,所以从后往前分析. 2.假设后面的人没说谎,并将此作为已知条件,然后从后往前依次给每个人找到合适的名次,输出所有能找到合适名次的人即可. 3.假定给第i个人安排名次,第i+1~n个人名次已经安排好,假如第i个人想占的名次被第j个人所占,那就从第j个人可以占的名次中再找个合适的名次给j,然后把空出来的这个名次给i,如果i可以占的所有名次都被占且占领的人找不到其他可以占的名

elixir中的truth和true

在elixir中, true 就是true 或者是:true 是一个原子 atom, 在其他语言中的true,这里叫做truth, 只要你不是false,nil ,就是truth, 当然 false和nil也是原子 所以说elixir中Boolean operators 是针对true a or b # true if a is true, otherwise ba and b # false if a is false, otherwise bnot a  # false if a is tr

codeforces Gym 100187L L. Ministry of Truth 水题

L. Ministry of Truth Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/problem/K Description Andrey works in the Ministry of Truth. His work is changing articles in newspapers and magazines so that they praise the Party an

【转载】Multitrack Audio with Structural Segmentation Ground Truth Annotations多轨音频分割

Multitrack Audio with Structural Segmentation Ground Truth Annotations Hargreaves, Steven URI: http://c4dm.eecs.qmul.ac.uk/rdr/handle/123456789/36 Date: 2013-11-27 Abstract: This dataset contains multitrack audio recordings of rock and pop songs, alo

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/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1427    Accepted Submission(s): 719 Problem Description After this year’s col

hdu 3729 I'm Telling the Truth

I'm Telling the Truth Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1377    Accepted Submission(s): 700 Problem Description After this year’s college-entrance exam, the teacher did a survey in

HDU 3729 I'm Telling the Truth (二分匹配)

题意:给定 n 个人成绩排名区间,然后问你最多有多少人成绩是真实的. 析:真是没想到二分匹配,....后来看到,一下子就明白了,原来是水题,二分匹配,只要把每个人和他对应的区间连起来就好,跑一次二分匹配,裸的. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #inc

论文笔记之:Playing for Data: Ground Truth from Computer Games

Playing for Data: Ground Truth from Computer Games ECCV 2016 Project Page:http://download.visinf.tu-darmstadt.de/data/from_games/index.html arXiv Paper : http://arxiv.org/pdf/1608.02192.pdf 摘要: 本文有意思哦,从游戏中的视频帧中得到新的训练数据,为什么用这些数据呢?众所周知,最近的计算机视觉很大程度上依赖于

URAL 1732 . Ministry of Truth KMP

题目来源:URAL 1732 . Ministry of Truth 题意:把第一个字符串处理一下 变成第二个 不要的字符改成下划线 空格不能改 思路:对第二个字符串单词分割 得到每一个单词后从第一个字符串中匹配 匹配成功 记录当前匹配的位置 然后下一个单词从x+2处在匹配 知道所有的单词都被匹配到 鄙视自己没想清楚写了半天 最后发现题目意思都错了 改了很多 最后代码和原来的完全不一样了 以后想清楚在写 样例 abcd和ab d输出ab_c abcx abcxx abcxx和abc abc ab