#.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
класса, который содержит одно значение на слот.