.NET CLI: как локальная переменная удаляется из стека, если она не находится сверху?

#.net

#.net

Вопрос:

Я пытаюсь понять, как работают стек и куча.

Итак, мой вопрос о стеке. Например, у нас есть следующий код:

 static void Main()
{
    int a = 1;
    int b = 2;

    Console.WriteLine(a);
}
 

Обе переменные будут помещены в стек, а переменная ‘b’ будет поверх переменной ‘a’.

Если в стеке есть только операции Push и Pop, как можно прочитать переменную ‘a’, не выскакивая из стека ‘b’?

Комментарии:

1. Я думаю, вы путаете концепцию стековой памяти и класса стека в C #. Они разделяют некоторые основные концепции, но это две совершенно разные вещи.

2. Она не извлекается — стек, содержащий локальные переменные, обрабатывается скорее как массив внутри метода., поэтому доступ к отдельным переменным можно получить с помощью смещения. (Упрощение, но должно дать вам представление …)

3. Я мог бы указать, что фактическое расположение переменных, полей и объектов в основном не имеет значения, с таким же успехом они могут быть на Луне, несмотря на всю разницу, которую это имеет для вас . Среда выполнения не должна соответствовать стандартному использованию стека x86 / 64, она может использовать любой другой метод с тем же результатом, включая запись его на бумаге

4. @charlieface Я подозреваю, что использование луны для локального хранилища может увеличить задержку, поскольку она находится на расстоянии около 1,25 световых секунд

5. @MarcGravell Верно, но это деталь реализации 🙂 Очевидно, что этот конкретный пример представляет собой довольно непрочную абстракцию, но принцип тот же: это не имеет ничего общего с C#

Ответ №1:

Локальные переменные определяются перед динамической / гибкой частью стека, так что на самом деле у вас есть (при условии отсутствия оптимизации):

  • определите a и b в стековом фрейме
  • вставьте 1 в динамический стек (после a и b)
  • запишите (вставьте) значение в верхней части стека в расположение
  • вставьте 2 в динамический стек
  • запишите (вставьте) значение в верхней части стека в расположение b
  • загрузите (переместите) значение из местоположения a в динамический стек
  • вызовите консоль.Строка записи

К значениям локальных переменных можно получить доступ в любое время; это просто относительные смещения от фрейма стека. Доступ к динамической части стека, используемой для переходных значений, обычно возможен только в строгом порядке, но это не то, что содержит местоположения, которые мы называем a и b.

Комментарии:

1. Вы сейчас говорите о стеке выполнения CLI? Я думаю, это не то, о чем здесь говорит OP.

2. @PMF Я прочитал вопрос несколько раз, и я придерживаюсь своей интерпретации вопроса

3. @MarcGravell Если OP ссылается на C #, понятия стека вообще нет, это просто ячейки памяти. OP должен ссылаться на CLI

4. Спасибо, я имел в виду именно stack в CLI. Извините за двусмысленность

Ответ №2:

Здесь у вас недоразумение. Оба a и b помещаются в один и тот же фрейм стека, поскольку они принадлежат одному и тому же методу. Внутри main всегда известно, что a находится по адресу Stackpointer 8, а b — по адресу Stackpointer 4 (например). Для стека выполнения каждый вызов метода представляет собой один кадр стека (содержащий все локальные переменные метода). Это отличается от Stack класса, который содержит одно значение на слот.