Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 15, средняя оценка - 4.80
iRomul
159 / 100 / 11
Регистрация: 17.10.2012
Сообщений: 480
Завершенные тесты: 1
#1

Выделение памяти на стеке - C++

13.07.2013, 17:27. Просмотров 2420. Ответов 8
Метки нет (Все метки)

Добрый день. Часто в учебниках и на форуме я встречал такое выражение как "переменная создаётся в (или на) стеке". Мне непонятно, что это значит. Ведь к стеку мы обращаемся через
Assembler
1
2
push ax
pop ax
например. Но как это связано с локальными переменными (да и вообще с выражением - выделение памяти на стеке)?
Спасибо.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.07.2013, 17:27
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Выделение памяти на стеке (C++):

Как происходит процесс выделения памяти в стеке и куче - C++
#include <stdio.h> #include <conio.h> #include <windows.h> #include "disc.h" void main() { SetConsoleCP(1251); ...

Распределение памяти. Динамическое выделение памяти - C++
an-1 an-2 ... a2

Выделение памяти, проверка на утечку памяти - C++
Интересуют два вопроса: 1. Правильно ли устроен алгоритм выделения, удаление и запись ячейки памяти? Может быть, есть более простые...

Выделение памяти - C++
Вот кусок кода, класс и функция добавления в список Класс занимает 64 бита, я добавляю 10 элементов в список - 640 бит Потом отнимаю...

Выделение памяти - C++
Доброго всем вечера. В книжке нашел задание: определить класс, представляющий стек. Сделал так, что при заполнении всего стека,...

Выделение памяти - C++
Часто возникает такая проблема, когда конфигурирую проект как Release происходит ошибка выделения памяти (при вызывании new), например...

8
Kuzia domovenok
1957 / 1810 / 142
Регистрация: 25.03.2012
Сообщений: 6,274
Записей в блоге: 1
13.07.2013, 18:26 #2
Во-первых, заталкивать в стек значения можно и просто обращаясь к регистру esp
Assembler
1
sub esp, 4; //запихнули в стек 4 байта. Никакого push для этого не обязательно
Подразумевается, что компилятор. Размещает локальные переменные, превращая код такой функции
C
1
2
3
4
void foo(){
int x;
x=1;
}
Во что-то похожее
Assembler
1
2
3
4
5
6
7
8
9
10
push ebp;
mov ebp, esp;
sub esp, 4;//Вот тут происходит заталкивание 4х байт в стек. 
;//Программисты Си, естесственно просто объявляют локальную переменную int x;
;// и думать о стеке не могут.
mov ecx, 1;
mov dword ptr[ebp-4], ecx;//ebp-4 это и есть адрес переменной икс. 
;//Догадайся почему нельзя сказать просто mov esp, ecx
mov esp, ebp;
pop ebp;
но всё зависит от компилятора и может быть не совсем так

Добавлено через 5 минут
Во-первых, заталкивать в стек значения можно и просто обращаясь к регистру esp
Assembler
1
sub esp, 4; //запихнули в стек 4 байта. Никакого push для этого не обязательно
Подразумевается, что компилятор. Размещает локальные переменные, превращая код такой функции
C
1
2
3
4
void foo(){
int x;
x=1;
}
Во что-то похожее
Assembler
1
2
3
4
5
6
7
8
9
push ebp;
mov ebp, esp;
sub esp, 4;//Вот тут происходит заталкивание 4х байт в стек. 
;//Программисты Си, естесственно просто объявляют локальную переменную int x;
;// и думать о стеке не могут.
mov dword ptr[ebp-4], 1;//ebp-4 это и есть адрес переменной икс. 
;//Догадайся почему нельзя сказать просто mov dword ptr[esp], 1
mov esp, ebp;
pop ebp;
но всё зависит от компилятора и может быть не совсем так
1
iRomul
159 / 100 / 11
Регистрация: 17.10.2012
Сообщений: 480
Завершенные тесты: 1
13.07.2013, 19:22  [ТС] #3
Воу воу. Вы меня простите, я в асме не силён, по-этому, если можно, по-порядку.
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Во-первых, заталкивать в стек значения можно и просто обращаясь к регистру esp
Assembler
1
sub esp, 4; //запихнули в стек 4 байта. Никакого push для этого не обязательно
Как так? Разве не add esp, 4 надо делать? Ведь вычитание (по идее) аналог pop

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Assembler
1
2
mov dword ptr[ebp-4], 1;//ebp-4 это и есть адрес переменной икс. 
;//Догадайся почему нельзя сказать просто mov dword ptr[esp], 1
Могу только предположить, что esp указывает на следующий элемент стека (сразу после 4 байт)

Только мне никак не понять строку:
Assembler
1
mov dword ptr[ebp-4], 1
Что в ней происходит? И dword - это не то же, что и dw в MASM?
Спасибо!
0
Tulosba
:)
Эксперт С++
4397 / 3233 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
14.07.2013, 00:04 #4
Цитата Сообщение от iRomul Посмотреть сообщение
"переменная создаётся в (или на) стеке"
Стек - условно, уже выделенная для программы память некоторого объема. Для этой памяти есть указатель - вершина стека. При создании новой переменной на стеке, указатель смещается на sizeof(тип переменной) и память инициализируется должным образом (конструктором). При уничтожении переменной (выход из области видимости) вызывается деструктор объекта и указатель стека смещается обратно на sizeof объекта. Альтернативный вариант подразумевает выделение памяти в куче (оператор new), и освобождение после работы (оператор delete).
1
iRomul
159 / 100 / 11
Регистрация: 17.10.2012
Сообщений: 480
Завершенные тесты: 1
14.07.2013, 02:01  [ТС] #5
Хорошо, допустим мне стало ясно, как располагаются переменные в стеке. Допустим мы создали штук 5 таких локальных переменных. Но как происходит обращение к ним? Через смещения относительно esp? Или как?
0
Kuzia domovenok
1957 / 1810 / 142
Регистрация: 25.03.2012
Сообщений: 6,274
Записей в блоге: 1
14.07.2013, 02:59 #6
dword ptr[ebp-4]
dword ptr[ebp-8]
как-то так. указывается смещение, относительно esp
1
iRomul
159 / 100 / 11
Регистрация: 17.10.2012
Сообщений: 480
Завершенные тесты: 1
14.07.2013, 03:05  [ТС] #7
Ясно, спасибо. Теперь понятно. Просто раньше я не знаю, что мы можем по элементам стека обращаться через указатель. Мне всегда казалось, что эту задачу выполняют только pop и push.
0
sharpey
138 / 128 / 21
Регистрация: 21.09.2008
Сообщений: 401
14.07.2013, 07:46 #8
Есть превосходно написанная, свободно распространяемая книга Столярова Андрея Викторовича "Программирование на языке ассемблера NASM для ОС Unix". В параграфе 2.6 рассмотрены все интересующие Вас детали.
Вообще аналогию стека как стопки листов (патронов в рожке автомата, стопки тарелок и т.п.) считаю крайне неудачной. Указатель стека - это лишь значение регистра SP/ESP на ячейки памяти, где размещаются данные. Из истории: регистр специального назначения R6 в 16-битном процессоре PDP-11 ныне почившей фирмы DEC выполнял то же самое действие (эх, прекрасный у них был ассемблер вместо уродливого Intel'овского). В процессоре PDP-11 была команда
Assembler
1
mov R0,-(SP)
что эквивалентно Intel x86
Assembler
1
push AX
при этом значение указателя стека уменьшается на размер операнда ДО выполнения операции, а извлечение из стека
Assembler
1
mov (SP)+,R0 / pop AX
приводит к изменению указателя стека ПОСЛЕ выполнения операции. Поэтому аналогия типа "для извлечения четвёртой тарелки из стопки от вершины стека мы берем третье слово (поскольку счёт идёт от нуля)"
Assembler
1
mov AX, DWORD PTR [SP+((4-1)*2)]
даёт искажённое представление, т.к. в этой аналогии нет возможности взять четвёртую тарелку из воздуха (т.е. адресоваться по отрицательному смещению, а это возможно).
Знание о том, как работает стек, нужно при рассмотрении работы подпрограмм (call, enter, leave), сохранении/восстановлении всех регистров (pusha/popa).

В свободное время неспешно читаю восьмисотстраничную "Practical Malware Analysis: The Hands-On Guide to Dissecting Malicious Software" авторов Michael Sikorski и Andrew Honig, вышедшую в 2012 году в издательстве No Starch Press, Inc. - про анализ зловредов. Затрагивается в т.ч. передача параметров в функцию соглашениями cdecl, pascal (stdcall), fastcall. Изумительная книга, даже несмотря на то, что написана на английском. Рекомендую к прочтению, хотя бы для общего развития. В Сети легко находится её электронный вариант.
1
Kastaneda
Jesus loves me
Эксперт С++
4689 / 2893 / 236
Регистрация: 12.12.2009
Сообщений: 7,356
Записей в блоге: 2
Завершенные тесты: 1
14.07.2013, 09:10 #9
Цитата Сообщение от iRomul Посмотреть сообщение
Но как происходит обращение к ним? Через смещения относительно esp? Или как?
Нет, esp не трогается. Создается т.н. стек фрейм (или фрем стека), обычно это делается при помощи ebp и он же (ebp) учавствует в адресации. Перед выходом из процедуры стек фрейм разрушается.
Вот можно почитать начиная с 2.1 Кадры стека.
1
14.07.2013, 09:10
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.07.2013, 09:10
Привет! Вот еще темы с ответами:

Выделение памяти - C++
Во время выполнения программы после ввода нескольких символов выводит ошибку: double free or corruption(out): 0x0000000001157010 ***...

До выделение памяти в С++ - C++
Всем приветик. Вообщем есть некоторые сложности с довыделение памяти... Что я хочу сделать: есть 2-х мерный массив (он ещё и квадратный)....

Выделение памяти(С = С++) - C++
Привет. Нужна помощь, в выделении памяти. Есть код на С, нужно перевести его в С++. int SaveFileOne(int i) { FILE *f; if ((f =...

Выделение памяти - C++
Эта программа должна забрать у системы 10 МБ, но диспетчер задач показывает, что программа забирает 163 МБ. Почему ? ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru