#c_sharp
Один мой друг спрашивает, возможна ли такая ситуация в C# когда в куче будет храниться адрес объекта (ссылка на объект) в стеке? С учетом того что используется только управляемый код. Возник спор)
Ответы
Ответ 1
Смотрите. Для начала, вопрос не имеет смысла в контекста языка C# в отрыве от его конкретной имплементации. Само по себе наличие стека и кучи — деталь имплементации Microsoft CLR, вполне возможны бесстековые имплементации. Если вы заглянете в спецификацию C# 5, вы увидите, что слово stack встречается там лишь в unsafe-контексте (например, stackalloc возвращает pointer, а не ссылку). Язык C#, за исключением unsafe-частей, не определяет, где именно и как будут храниться ваши объекты и значения. Поэтому имеет смысл рассматривать вопрос лишь в контексте Microsoft CLR. Для неё проще всего заглянуть в спецификацию. Согласно спецификации (§I.12.1.1.2), управляемые адреса объектов делятся на ссылки на объекты (O) и управляемые указатели (&). Объекты располагаются всегда в куче, поэтому нас интересуют лишь управляемые указатели. Заглянем в §I.8.2.1.1 Managed pointers and related types: Managed pointer types are only allowed for local variable (§I.8.6.1.3) and parameter signatures (§I.8.6.1.4); they cannot be used for field signatures (§I.8.6.1.2), as the element type of an array (§I.8.9.1), and boxing a value of managed pointer type is disallowed (§I.8.2.4). Using a managed pointer type for the return type of methods (§I.8.6.1.5) is not verifiable (§I.8.8). [Rationale: For performance reasons items on the GC heap may not contain references to the interior of other GC objects, this motivates the restrictions on fields and boxing. Further returning a managed pointer which references a local or parameter variable may cause the reference to outlive the variable, hence it is not verifiable. end rationale] То же на русском (перевод мой): Тип «управляемый указатель» разрешён лишь для локальных переменных (§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; } } P. S.: В C# 7.2 появился тип Span, который может содержать ссылки на стек вне unsafe-контекста. Но вы не можете положить Span в кучу.
Комментариев нет:
Отправить комментарий