![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| Mayk |
|
|||
![]() ^аВаТаР^ сообщение>> ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 2616 Регистрация: 22.5.2005 Где: за границей разум а Репутация: 45 Всего: 134 |
En_t_end
Вот в том то и дело, что стэк один на всех во всем потоке программы. В него соответственно ВСЁ пихается. Блин, попробую проиллюстрировать стек на примере той программы, что привел. Предположим что в начальный момент времени main() стэк пуст Предположим, что он растет к старшим адресам(это не так, но имхо так понятнее... Во всяком случае мне) main(){ int x,y,z; В стек добавляются локальные переменные SS:0000 x SS:0004 y SS:0008 z (SS - сегмент стека) x=a(); SS:000c main+xx ...запускается a() SS:0000 x SS:0004 y SS:0008 z SS:000c main+xx a() пихает в стек tmp(увеличивает значение стека на размер tmp) tmp=0 tmp распологается по адресу SS:0010. SS:0000 x SS:0004 y SS:0008 z SS:000c main+xx SS:0010 tmp Функция возвращает указатель на tmp, то есть SS:0010. Теперь a() завершается. Она уничтожает ВСЕ локальные переменные(уменьшает значение стека на размер tmp) Выпихивает main+xx, передает туда управление. Всё это повторяется трижды. Это сообщение отредактировал(а) Mayk - 22.6.2005, 18:00 -------------------- Здесь был кролик. Но его убили. Человеки < кроликов, йа считаю. |
|||
|
||||
| En_t_end |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2074 Регистрация: 4.12.2004 Репутация: 1 Всего: 20 |
comcon1
Значит все-таки в глобальном стеке значение полученное в результате работы функции и после конца работы сохраняется ? |
|||
|
||||
| _hunter |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 8564 Регистрация: 24.6.2003 Где: Europe::Ukraine:: Kiev Репутация: 16 Всего: 98 |
вот:
тебе илюстрация призрака... tmp1 должен быть равным 1, tmp2 -- 2, но это не так -------------------- Tempora mutantur, et nos mutamur in illis... |
|||
|
||||
| En_t_end |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2074 Регистрация: 4.12.2004 Репутация: 1 Всего: 20 |
_hunter
Я изменил пример, тот пример как раз был тем случаем с явным выделением памяти через new. |
|||
|
||||
| comcon1 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 838 Регистрация: 11.6.2005 Где: Москва ДАС-МГУ Репутация: 12 Всего: 17 |
2 En_t_end. То, как мы ограничиваем понятие "функция" в С++ и то, как это реализовано в ASM - это разные вещи.
Кроме возвращаемых параметров, есть еще входные параметры, которые тоже передаются через стек. В ASM функция - это то, что идет между адрессом начала (куда нас кидает команда CALL) и командой RET, которая кидает нас обратно в тело программы. В С++-функцию (да и вообще функцию любого высокоуровневого языка) еще входят передача параметров перед CALL-ом и реанимация стека после RET-а. Кстати, где-то я читал, что для корректного удаления объекта класса delete-ом нужно явно задавать деструктор. С чем это связано?? Мож кто в курсе? Я вот просто разницы не вижу. Это сообщение отредактировал(а) comcon1 - 22.6.2005, 18:08 |
|||
|
||||
| En_t_end |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2074 Регистрация: 4.12.2004 Репутация: 1 Всего: 20 |
Дык чего, если у меня пол функций в программе, как в примере у _hunter, то ни сегодня завтра все рухнет ? Что переделывать на явное выделение памяти ?
Добавлено @ 18:14 Ладно... я думаю тему можно удалять, ибо я наплел тут полную чушь, как и ожидал - пойду читать соответсвующую главу Страуструпа. |
|||
|
||||
| _hunter |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 8564 Регистрация: 24.6.2003 Где: Europe::Ukraine:: Kiev Репутация: 16 Всего: 98 |
в таком примере получиш призрака
+ посмотри мой пример. comcon1, свой деструктор нужно писать только в случае явного выделения памяти ( потому что деструктор по умолчанию ( который компилятор в любом случае прикрутит ) просто не знает что с ней ( с памятью ) делать -- может ее оставить для чего-нить нужно ) Добавлено @ 18:16 En_t_end, если как у меня в примере -- странно что еще не рухнуло -------------------- Tempora mutantur, et nos mutamur in illis... |
|||
|
||||
| comcon1 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 838 Регистрация: 11.6.2005 Где: Москва ДАС-МГУ Репутация: 12 Всего: 17 |
Как можно оставить память после деструкции класса? Допустим я ничего не пишу в деструкторе. И делаю указателю на класс new-delete. Как мне обратиться к этой памяти?
Тему ни в коем случае не удалять, ибо отведение памяти - вопрос один из самых важных!!! Это сообщение отредактировал(а) comcon1 - 22.6.2005, 18:25 |
|||
|
||||
| _hunter |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 8564 Регистрация: 24.6.2003 Где: Europe::Ukraine:: Kiev Репутация: 16 Всего: 98 |
написать в конструкторе new (простейший пример )
к какой? к классу? SomeClass* someClass = new SomeClass(); someClass->SomeMethod(); -------------------- Tempora mutantur, et nos mutamur in illis... |
||||
|
|||||
| comcon1 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 838 Регистрация: 11.6.2005 Где: Москва ДАС-МГУ Репутация: 12 Всего: 17 |
Да нет. Я не про это. Допустим,я создал объект
SomeClass *myclass = new SomeClass(); Чего-то сделал. myclass->mymethod(); А теперь вызвал деструктор, ..... delete myclass; .... в котором ничего не прописал. Ты говорил, что память остается. Как после всего этого можно к ней обратиться, если она осталась?? Или если освобождения памяти не прописано в деструкторе, то после всех вышеперечисленных манипуляций, с классом можно продолжать работать??? |
|||
|
||||
| _hunter |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 8564 Регистрация: 24.6.2003 Где: Europe::Ukraine:: Kiev Репутация: 16 Всего: 98 |
я же написал: память выделяется в конструкторе
т.е.
если эту память потом не грохнуть в деструкторе она просто потеряется и доступ к ней ты не получиш... -------------------- Tempora mutantur, et nos mutamur in illis... |
|||
|
||||
| comcon1 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 838 Регистрация: 11.6.2005 Где: Москва ДАС-МГУ Репутация: 12 Всего: 17 |
Все понятно. thx. Этих я удалять стараюсь. Забываю иногда, правда :-)
|
|||
|
||||
| En_t_end |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2074 Регистрация: 4.12.2004 Репутация: 1 Всего: 20 |
Короче я тему удаляю, ибо я получил ответ на свой вопрос(ламерский), получил на свой и comcon1. Так как сама тема побуждает к флейму её стоит удалить.
|
|||
|
||||
| vadims |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 305 Регистрация: 8.6.2005 Репутация: 2 Всего: 17 |
ИМХО: тут просто перемешали понятия Для простоты считаем приложение 16-битным и int(teger) имеет размерность 2 байта, а указатель 4 байта -------------------------------------------------------------------------------------------------- (1) Память делиться а. сегмент(ы) кода - CS:IP б. cтек (один для всех) - SS:SP в. глобальный cегмент данных - один для всех глобальных переменных и переменных типа static г. дополнит. глобальные сегменты данных - свой для каждой пременной/массива типа far и huge д. куча локальная и глобальная локальные переменные функции void f( void ) { int a,b; char mas[100]; ... } резервируются в стеке ; те после сохранения регистров внутри функции push di push si ; идет собственно резервирование sub SP, 104 ; 2+2+100 mov bp, SP ; работа с переменными идет через SS:[bp+смешение до переменной] . . . ; возвращаем стеку зарезервированную область add SP, 104 pop si // восстанавливаем регистры pop di ret // возврат те по возвращению из функции, все локальные переменные описанные в ней по сути уже неопределены, хотя физически их значения остаются; там уж зависит от того насколько последующий код использует стек Один нюанс, если локальная переменная описана как static, то она распологается в глобальном сегменте данных и именно поэтому ее значение корректно при повторном входе в функцию Что собственно можно проверить на примере приведенном Mayk, рез-тат будет 2 2 2 То что получаем через new - в куче, от функции не зависит Хотя опять нюансы - если будет выделено в локальной куче, то этот участок памяти все равно освободиться по завершению программы, если в глобальной то после перезагрузки. Лучше не рисковать и освобождать обязательно -------------------------------------------------------------------------------------------------- (2) Существует 2 подхода к вызову процедур/функций, передаче аргументов и возврату значений Делаем мне скидку на то что немного подзабыл синтаксис паскаля и ассемблер 1. Паскалевский - func( integer a,b, var integer ra, rb ) : pointer ptr = func( 1, 2, ra, rb); при вызове а) входные параметры в стек, начиная с последнего б) выходные параметры будут возвращены тоже ч/p стек, для чего перед вызовом SP уменьшается на размер необходимый для их хранения, в нащем случае (ra,rb и возвращаемый указатель) 2+2+4=8 ; входные параметры пихаются в стек mov ax, 2 ; b push ax mov ax, 1 ; a push ax sub SP, 8 ; резервируем место в стеке для возвращаемых значений call func ; адрес возврата в стек, те SP = SP-4 mov ax, SS:[SP+0] ; результат функции в ptr mov LOW(ptr),ax mov ax, SS:[SP+2] mov HIGH(ptr),ax mov ax, SS:[SP+4] ; rb mov rb, ax mov ax, SS:[SP+6] ; ra mov ra, ax add SP, 8 ; возвращаем стек в исходное состояние 2. C'шный void *func( int a, int b ) ptr = func( 1, 2); при вызове а) входные параметры в стек, начиная с первого б) возвращаться может только одно значение и делается это через регистры al или ax или dx:ax ; входные параметры пихаются в стек mov ax, 1 ; a push ax mov ax, 2 ; b call func ; адрес возврата в стек, те SP = SP-4 mov LOW(ptr),ax mov HIGH(ptr),ax -------------------------------------------------------------------------------------------------- -------------------- Cpu not found ! Press any key for software emulation. |
|||
|
||||
| comcon1 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 838 Регистрация: 11.6.2005 Где: Москва ДАС-МГУ Репутация: 12 Всего: 17 |
Хм. Не знал, что в Паскале и С разница такая. Я Паскальный, значить, описал. Ну да ладно - факт тот, что стек реанимируется, и ладно.
В репу б тебе поставил, да 100 нету |
|||
|
||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |