![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| En_t_end |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2074 Регистрация: 4.12.2004 Репутация: 1 Всего: 20 |
Вот внезапно в голову забралась мысль
|
|||
|
||||
| Дрон |
|
|||
![]() Java-ненавистник :) ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3179 Регистрация: 29.12.2002 Где: Санкт-Петербург Репутация: 10 Всего: 93 |
Не будет -------------------- Да. Именно так. |
|||
|
||||
| En_t_end |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2074 Регистрация: 4.12.2004 Репутация: 1 Всего: 20 |
Дрон
Чем докажешь ? |
|||
|
||||
| Дрон |
|
|||
![]() Java-ненавистник :) ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3179 Регистрация: 29.12.2002 Где: Санкт-Петербург Репутация: 10 Всего: 93 |
С++ это не Java и не C#. Он ссылки на объекты не контролирует.
-------------------- Да. Именно так. |
|||
|
||||
| En_t_end |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2074 Регистрация: 4.12.2004 Репутация: 1 Всего: 20 |
Дрон
Я говорю про контроль НЕ ссылок, а переменных... они в таких точно не уничтожаются. Сам попробуй. |
|||
|
||||
| Дрон |
|
|||
![]() Java-ненавистник :) ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3179 Регистрация: 29.12.2002 Где: Санкт-Петербург Репутация: 10 Всего: 93 |
Что значит не уничтожается? Память освобождается и некоторое время будет ещё хранить значения, пока её какая-нибудь функция не перезапишет. -------------------- Да. Именно так. |
|||
|
||||
| _hunter |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 8564 Регистрация: 24.6.2003 Где: Europe::Ukraine:: Kiev Репутация: 16 Всего: 98 |
если ты возвращаеш char* то где-то ( пусть в функции ) был new. вот эта _память_ и висит, но висит она не на стеке. а сам указатель возвращается по значению ( т.е. т он не висит... )
-------------------- Tempora mutantur, et nos mutamur in illis... |
|||
|
||||
| En_t_end |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2074 Регистрация: 4.12.2004 Репутация: 1 Всего: 20 |
Дрон
стек простейшего метода chat* tempo(void); - будет существовать, как мне кажется до тех пор, пока эта ссылка не будет обнулена: char *tempo_ptr = tempo(void); Согласен ? |
|||
|
||||
| Mayk |
|
|||
![]() ^аВаТаР^ сообщение>> ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 2616 Регистрация: 22.5.2005 Где: за границей разум а Репутация: 45 Всего: 134 |
En_t_End, проверь
Следуя твоей логики должно быть выведено 0 1 2. Следуя логики Си это совсем не так. Добавлено @ 17:34 En_t_End У функций НЕТ стека. Стек один. -------------------- Здесь был кролик. Но его убили. Человеки < кроликов, йа считаю. |
|||
|
||||
| En_t_end |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2074 Регистрация: 4.12.2004 Репутация: 1 Всего: 20 |
_hunter
С new - это другой случай... там Си работает с динамической памятью - поэтому по сути указатель указыват на некоторую область памяти, причем стек функции не будет управлять ею. ИМХО Добавлено @ 17:40 Mayk Не понял... как это ? А как же вся та инфа, из которой я понял, что функция или процедура - это мини программа, соответсвенно... стек должен быть, как тогда реализовано управление переменными ? То что есть глобальный стек я не оспариваю. Добавлено @ 17:41 Дрон Бьярн Страуструп по моему писал, что ни одна переменная не будет уничтожена, пока на неё будет ссылаться указатель. |
|||
|
||||
| comcon1 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 838 Регистрация: 11.6.2005 Где: Москва ДАС-МГУ Репутация: 12 Всего: 17 |
Посмотрим в ассемблер. Когда возвращается указатель перед вызовом функции стек смещается:
stack:.......................................перед вызовом:...........................................после call (вызов функции) o|o|o|o|o|*........----->......... o|o|o|o|o|_memory_for pointer_| ---->...o|o|o|o|o|_memory_for_pointer_|_back_address_ далее в то место, где _memory_for_pointer_, записывается указатель. Мы выходим из функции: команда ret Поп-ает адресс возврата. и смещает туда каретку...теперь мы делаем Pop и забираем результат. o|o|o|o|o|_memory_for_pointer_.......................................------>.................................o|o|o|o|o| Стек снова в исходном состоянии!! Если хотите, можно подробнее. Но разницы в том, что возвращать, нет. Тока память разная в стеке отводится перед вызовом call Это сообщение отредактировал(а) comcon1 - 22.6.2005, 17:48 |
|||
|
||||
| _hunter |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 8564 Регистрация: 24.6.2003 Где: Europe::Ukraine:: Kiev Репутация: 16 Всего: 98 |
тогда я не понял что ты возвращаеш в своем указателе ( если ты под него память не выделяеш )...
но даже в таком случае вернется 4байта по значению и стек благополучно хрохнется -------------------- Tempora mutantur, et nos mutamur in illis... |
|||
|
||||
| En_t_end |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2074 Регистрация: 4.12.2004 Репутация: 1 Всего: 20 |
_hunter
Вот пример... ну не скажешь же ты, что потом юзая в классе то что получу в результате этой функции я буду юзать призрака ?
Это сообщение отредактировал(а) En_t_end - 22.6.2005, 17:57 |
|||
|
||||
| comcon1 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 838 Регистрация: 11.6.2005 Где: Москва ДАС-МГУ Репутация: 12 Всего: 17 |
Програма выполняется по мере считывания ее из памяти. Есть в регистрах процессора указатель на место, где мы считываем (кажется IP) Instruction Pointer.
Здесь дело в том, что в функцию мы входим (команда CALL). И в стек заносится аддресс IT того места, откуда мы прыгаем в функцию. Внутри функции мы производим некоторые операции и возвращаемся (команда RET). И ВЕРХУШЕЧНЫМ ЭЛЕМЕНТОМ ДОЛЖЕН БЫТЬ АДДРЕСС возврата в тело прораммы. Иначе будет RunTimeError. Из-за этого в стеке сначала отводят память (смещая указатель на вершину, стек в процессоре в обр. направлении) SUB SP, 04 SUB - вычесть. SP - STACK POINTER. А потом уже входим в функцию. CALL 0AFFF (аддресс входа туда будет смещен IP) Ну а когда мы вернулись - мы берем из стека значение и приводим его в исходное состояние. Никаких перегрузок. Это сообщение отредактировал(а) comcon1 - 22.6.2005, 17:55 |
|||
|
||||
| _hunter |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 8564 Регистрация: 24.6.2003 Где: Europe::Ukraine:: Kiev Репутация: 16 Всего: 98 |
не скажу
потому что ты явно выделил память ( и никто короме тебя ее удаялть не будет ) а вот если где-то перед юзанеем сделаеш delete[] ( причем не обязательно tempo ) то именно призрака ты и получиш... -------------------- Tempora mutantur, et nos mutamur in illis... |
|||
|
||||
| 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 нету |
|||
|
||||
| vadims |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 305 Регистрация: 8.6.2005 Репутация: 2 Всего: 17 |
Кстати, пока курил - осознал, что кое-что попутал - уж очень давно я библиотек на asm'е не писал.
1. Если речь о методе класса то передается еще указатель на объект 2. Похоже я попутал работу с возвращаемыми параметрами в паскалевском вызове. Вот теперь смутно припоминается что они не в стеке резервируются, а передаются через указатели те push <входные параметры> push <адреса выходных параметров> call func add sp, <на сколько изменили указатель передаче параметров> 3. В С-шном вызове, помимо возврата BYTE,WORD,DWORD и указателя через dx.ax, можно ведь вернуть и структуру - в этом случае она точно резервируется в стеке перед вызовом функции (как я описывал работу с var аргументами в паскале) и еще после call , обязательно надо восстановить стек прибавив к SP все то что мы использовали при передаче/резервировании, те add SP, <size args> Но основной вопрос ведь был, как и где распределяется память в зависимости от описания переменных и вызова функций - на него я ответил по моему корректно
Переведи, а что значит '100 нету' Я как-то не очень владею этой феней -------------------- Cpu not found ! Press any key for software emulation. |
|||
|
||||
| En_t_end |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2074 Регистрация: 4.12.2004 Репутация: 1 Всего: 20 |
Это означает, что у чела нет 100 сообщений, чтобы иметь право повышать тебе или понижать репутацию. ЗЫ не беспокойся, я тебе повысил |
|||
|
||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |