如果局部(但未使用)变量是对对象的唯一强引用,那么符合标准的 C# 编译器是否可以优化它?

发布于 2024-08-31 01:01:26 字数 1792 浏览 4 评论 0原文

另请参阅这些相关资源:


换句话说:

一个对象可以被本地引用吗? 变量在之前被回收 变量超出范围(例如 因为变量已被赋值,但是 然后不再使用),或者是这样 保证不符合条件的对象 垃圾回收直到变量 超出范围?

让我解释一下:


void Case_1()
{
    var weakRef = new WeakReference(new object());

    GC.Collect();  // <-- doesn't have to be an explicit call; just assume that
                   //     garbage collection would occur at this point.

    if (weakRef.IsAlive) ...
}

在这个代码示例中,我显然必须计划新的对象被垃圾收集器回收的可能性;因此是 if 语句。

(请注意,我使用 weakRef 的唯一目的是检查新的 object 是否仍然存在。)


void Case_2()
{
    var unusedLocalVar = new object();
    var weakRef = new WeakReference(unusedLocalVar);

    GC.Collect();  // <-- doesn't have to be an explicit call; just assume that
                   //     garbage collection would occur at this point.

    Debug.Assert(weakRef.IsAlive);
}

此代码示例相对于上一个示例的主要变化是新的对象被局部变量(unusedLocalVar)强引用。但是,在创建弱引用 (weakRef) 后,该变量将不再使用。


问题:如果合格的 C# 编译器发现 unusedLocalVar<,是否允许将 Case_2 的前两行优化为 Case_1 的前两行/code> 仅在一个地方使用,即作为 WeakReference 构造函数的参数?即 Case_2 中的断言是否有可能失败?

See also these related resources:


In other words:

Can an object referenced by a local
variable be reclaimed before the
variable goes out of scope (eg.
because the variable is assigned, but
then not used again), or is that
object guaranteed to be ineligible for
garbage collection until the variable
goes out of scope?

Let me explain:


void Case_1()
{
    var weakRef = new WeakReference(new object());

    GC.Collect();  // <-- doesn't have to be an explicit call; just assume that
                   //     garbage collection would occur at this point.

    if (weakRef.IsAlive) ...
}

In this code example, I obviously have to plan for the possibility that the new'ed object is reclaimed by the garbage collector; therefore the if statement.

(Note that I'm using weakRef for the sole purpose of checking if the new'ed object is still around.)


void Case_2()
{
    var unusedLocalVar = new object();
    var weakRef = new WeakReference(unusedLocalVar);

    GC.Collect();  // <-- doesn't have to be an explicit call; just assume that
                   //     garbage collection would occur at this point.

    Debug.Assert(weakRef.IsAlive);
}

The main change in this code example from the previous one is that the new'ed object is strongly referenced by a local variable (unusedLocalVar). However, this variable is never used again after the weak reference (weakRef) has been created.


Question: Is a conforming C# compiler allowed to optimize the first two lines of Case_2 into those of Case_1 if it sees that unusedLocalVar is only used in one place, namely as an argument to the WeakReference constructor? i.e. is there any possibility that the assertion in Case_2 could ever fail?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

別甾虛僞 2024-09-07 01:01:26

C# 编译器做什么并不重要 - 一旦本地引用在方法体中不再存在,JITter/GC 就可以清理它们。查看 GC.KeepAlive 的文档

另外,这个PowerPoint 演示文稿,特别是从幻灯片 30 开始,有助于解释 JIT/GC 可以做什么。

It doesn't matter what the C# compiler does - the JITter/GC are allowed to clean up local references once they're no longer alive in a method body. Look at the docs for GC.KeepAlive

Also, this powerpoint presentation, especially from slide 30 onwards, helps to explain what the JIT/GC can get up to.

魂ガ小子 2024-09-07 01:01:26

虽然我的问题已得到解答,但我想我应该发布我刚刚在 MSDN 博客文章 "WP7:GC 何时将局部变量视为垃圾" 作者:abhinaba

[T]ECMA 规范(ECMA 334 第 10.9 节)[...] 指出

“例如,如果作用域内的局部变量是对对象的唯一现有引用,但在从过程中的当前执行点开始的任何可能的继续执行中都不会引用该局部变量,实现可能(但不要求)将该对象视为不再使用。”​​

这说明了一切。上述文章还指出,.NET 框架(至少在发布模式下)将执行预测分析并释放此类对象,而 .NET Compact Framework 不会(出于性能原因)。

While my question has been answered, I thought I'd post this relevant piece of information I just found on the MSDN blog article "WP7: When does GC Consider a Local Variable as Garbage" by abhinaba:

[T]he ECMA specification (ECMA 334 Section 10.9) […] states

“For instance, if a local variable that is in scope is the only existing reference to an object, but that local variable is never referred to in any possible continuation of execution from the current execution point in the procedure, an implementation might (but is not required to) treat the object as no longer in use.”

This says it all. The mentioned article also says that the .NET framework (at least in Release mode) will perform predictive analysis and free such objects, while the .NET Compact Framework won't (for performance reasons).

孤芳又自赏 2024-09-07 01:01:26

如果符合标准的 C# 编译器发现未使用的 LocalVar 仅在一个地方使用(即作为 WeakReference 构造函数的参数),是否允许将 Case_2 的前两行优化为 Case_1 的前两行?

这两个定义是等效的,因此从一个定义转换到另一个定义并不是“优化”,因为两者都没有更有效。

即 Case_2 中的断言是否有可能失败?

是的。生产编译器不太可能保留不必要的引用,因此它将被删除,GC 不会将其视为全局根并会收集该对象。

请注意,垃圾收集器看不到您的程序的变量和作用域。当您的代码到达垃圾收集器时,这些高级概念早已被编译掉了。 GC 只看到寄存器、线程堆栈和全局变量。

Is a conforming C# compiler allowed to optimize the first two lines of Case_2 into those of Case_1 if it sees that unusedLocalVar is only used in one place, namely as an argument to the WeakReference constructor?

The two definitions are equivalent so transforming from one to the other is not an "optimization" because neither is more efficient.

i.e. is there any possibility that the assertion in Case_2 could ever fail?

Yes. A production compiler is not likely to retain a reference unnecessarily so it will be removed, the GC will not see it as a global root and will collect that object.

Note that garbage collectors do not see your program in terms of variables and scope. Those high-level concepts have long since been compiled away by the time your code gets to the garbage collector. The GC sees only registers, thread stacks and global variables.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文