RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 913272
Accepted
Nick Proskuryakov
Nick Proskuryakov
Asked:2020-11-29 23:19:45 +0000 UTC2020-11-29 23:19:45 +0000 UTC 2020-11-29 23:19:45 +0000 UTC

堆栈上对象的 C# 地址

  • 772

我的一个朋友问,在C#中,当堆将对象的地址(对对象的引用)存储在堆栈上时,是否可能出现这种情况?鉴于仅使用托管代码。发生争议)

c#
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    VladD
    2020-11-30T03:22:59Z2020-11-30T03:22:59Z

    看。

    首先,这个问题在 C# 语言的上下文中没有意义,与它的具体实现隔离开来。就其本身而言,堆栈和堆的存在是 Microsoft CLR 实现的一个细节,无堆栈实现是很有可能的。如果您查看C# 5 规范,您会发现单词 stack 仅出现在不安全的上下文中(例如,它stackalloc返回指针,而不是引用)。C# 语言,除了不安全的部分,并没有准确定义对象和值的存储位置和方式。

    因此,仅在 Microsoft CLR 的上下文中考虑该问题是有意义的。对她来说,最简单的方法就是看说明书。

    根据规范(§I.12.1.1.2),托管对象地址分为对象引用(O)和托管指针(&)。对象总是在堆上,所以我们只对托管指针感兴趣。

    让我们看一下§I.8.2.1.1 托管指针和相关类型:

    托管指针类型仅允许用于局部变量(§I.8.6.1.3)和参数签名(§I.8.6.1.4);它们不能用于字段签名(§I.8.6.1.2),因为数组的元素类型(§I.8.9.1),并且不允许对托管指针类型的值进行装箱(§I.8.2.4) . 对方法的返回类型(§I.8.6.1.5)使用托管指针类型是不可验证的(§I.8.8)。

    [理由:出于性能原因,GC堆上的项目可能不包含对其他GC对象内部的引用,这激发了对字段和装箱的限制。进一步返回引用局部变量或参数变量的托管指针可能会导致引用比变量寿命更长,因此它是不可验证的。结束理由]

    俄语相同(我的翻译):

    托管指针类型仅允许用于局部变量 (§I.8.6.1.3) 和形式参数 (§I.8.6.1.4);它不能用作字段类型 (§I.8.6.1.2) 或数组元素类型 (§I.8.9.1)。此外,不允许托管指针值装箱(§I.8.2.4)。使用托管指针作为方法的返回类型(§I.8.6.1.5)会导致无法验证的代码(§I.8.8)。

    [动机:垃圾收集器服务的对象,出于性能原因,不应包含指向其他收集对象中间的指针,这迫使我们对边距和包装设置限制。此外,将托管指针返回到局部变量或参数可能会导致指针的生命周期超过变量的生命周期,从而导致无法验证。动机结束]

    因此,我们看到从堆到堆栈的(托管)指针是被禁止的:托管指针不能在堆上结束。

    并且从堆到堆栈的非托管指针是可能的,例如:

    unsafe class U
    {
        char* p;
        unsafe U()
        {
            char* q = stackalloc char[1];
            p = q;
        }
    }
    

    PS:C# 7.2引入了 typeSpan<T>,它可以包含不安全上下文之外的堆栈引用。但是你不能放在Span<T>一堆。

    • 8

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5