Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Мнение по указателям в рамках отдельных процедур, ИМХО на всю тему... просто мысли вслух 
:(
    Опции темы
Mayk
Дата 22.6.2005, 17:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 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


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
En_t_end
Дата 22.6.2005, 17:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2074
Регистрация: 4.12.2004

Репутация: 1
Всего: 20



comcon1
Значит все-таки в глобальном стеке значение полученное в результате работы функции и после конца работы сохраняется ?
PM MAIL ICQ Skype GTalk Jabber   Вверх
_hunter
Дата 22.6.2005, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 8564
Регистрация: 24.6.2003
Где: Europe::Ukraine:: Kiev

Репутация: 16
Всего: 98



вот:
Код

int* someFunction(int test)
{
    int someVariable = test;
    return &someVariable;
}

#pragma argsused
WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    int data;
    data = 1;
    int* tmp1 = someFunction(data);
    data = 2;
    int* tmp2 = someFunction(data);
    return 0;
}

тебе илюстрация призрака...
tmp1 должен быть равным 1, tmp2 -- 2, но это не так


--------------------
Tempora mutantur, et nos mutamur in illis...
PM ICQ   Вверх
En_t_end
Дата 22.6.2005, 18:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2074
Регистрация: 4.12.2004

Репутация: 1
Всего: 20



_hunter
Я изменил пример, тот пример как раз был тем случаем с явным выделением памяти через new.
PM MAIL ICQ Skype GTalk Jabber   Вверх
comcon1
Дата 22.6.2005, 18:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 838
Регистрация: 11.6.2005
Где: Москва ДАС-МГУ

Репутация: 12
Всего: 17



2 En_t_end. То, как мы ограничиваем понятие "функция" в С++ и то, как это реализовано в ASM - это разные вещи.
Кроме возвращаемых параметров, есть еще входные параметры, которые тоже передаются через стек. В ASM функция - это то, что идет между адрессом начала (куда нас кидает команда CALL) и командой RET, которая кидает нас обратно в тело программы. В С++-функцию (да и вообще функцию любого высокоуровневого языка) еще входят передача параметров перед CALL-ом и реанимация стека после RET-а.

Кстати, где-то я читал, что для корректного удаления объекта класса delete-ом нужно явно задавать деструктор.
С чем это связано?? Мож кто в курсе? Я вот просто разницы не вижу.

Это сообщение отредактировал(а) comcon1 - 22.6.2005, 18:08


--------------------
PM MAIL   Вверх
En_t_end
Дата 22.6.2005, 18:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2074
Регистрация: 4.12.2004

Репутация: 1
Всего: 20



Дык чего, если у меня пол функций в программе, как в примере у _hunter, то ни сегодня завтра все рухнет ? Что переделывать на явное выделение памяти ?
Добавлено @ 18:14
Ладно... я думаю тему можно удалять, ибо я наплел тут полную чушь, как и ожидал - пойду читать соответсвующую главу Страуструпа.
PM MAIL ICQ Skype GTalk Jabber   Вверх
_hunter
Дата 22.6.2005, 18:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 8564
Регистрация: 24.6.2003
Где: Europe::Ukraine:: Kiev

Репутация: 16
Всего: 98



в таком примере получиш призрака
+ посмотри мой пример.

comcon1, свой деструктор нужно писать только в случае явного выделения памяти ( потому что деструктор по умолчанию ( который компилятор в любом случае прикрутит ) просто не знает что с ней ( с памятью ) делать -- может ее оставить для чего-нить нужно )
Добавлено @ 18:16
En_t_end, если как у меня в примере -- странно что еще не рухнуло smile


--------------------
Tempora mutantur, et nos mutamur in illis...
PM ICQ   Вверх
comcon1
Дата 22.6.2005, 18:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 838
Регистрация: 11.6.2005
Где: Москва ДАС-МГУ

Репутация: 12
Всего: 17



Как можно оставить память после деструкции класса? Допустим я ничего не пишу в деструкторе. И делаю указателю на класс new-delete. Как мне обратиться к этой памяти? smile

Тему ни в коем случае не удалять, ибо отведение памяти - вопрос один из самых важных!!!

Это сообщение отредактировал(а) comcon1 - 22.6.2005, 18:25


--------------------
PM MAIL   Вверх
_hunter
Дата 22.6.2005, 18:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 8564
Регистрация: 24.6.2003
Где: Europe::Ukraine:: Kiev

Репутация: 16
Всего: 98



Цитата
Как можно оставить память после деструкции класса?

написать в конструкторе new (простейший пример )
Цитата
Как мне обратиться к этой памяти?

к какой? к классу?
SomeClass* someClass = new SomeClass();
someClass->SomeMethod();


--------------------
Tempora mutantur, et nos mutamur in illis...
PM ICQ   Вверх
comcon1
Дата 22.6.2005, 18:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 838
Регистрация: 11.6.2005
Где: Москва ДАС-МГУ

Репутация: 12
Всего: 17



Да нет. Я не про это. Допустим,я создал объект
SomeClass *myclass = new SomeClass();
Чего-то сделал.
myclass->mymethod();
А теперь вызвал деструктор, .....
delete myclass;
.... в котором ничего не прописал.
Ты говорил, что память остается. Как после всего этого можно к ней обратиться, если она осталась??
Или если освобождения памяти не прописано в деструкторе, то после всех вышеперечисленных манипуляций, с классом можно продолжать работать??? smile


--------------------
PM MAIL   Вверх
_hunter
Дата 22.6.2005, 18:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 8564
Регистрация: 24.6.2003
Где: Europe::Ukraine:: Kiev

Репутация: 16
Всего: 98



я же написал: память выделяется в конструкторе
т.е.
Код

SomeClass::SomeClass()
{
    someVariable = new...
}

если эту память потом не грохнуть в деструкторе она просто потеряется и доступ к ней ты не получиш...


--------------------
Tempora mutantur, et nos mutamur in illis...
PM ICQ   Вверх
comcon1
Дата 22.6.2005, 18:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 838
Регистрация: 11.6.2005
Где: Москва ДАС-МГУ

Репутация: 12
Всего: 17



Все понятно. thx. Этих я удалять стараюсь. Забываю иногда, правда :-)


--------------------
PM MAIL   Вверх
En_t_end
Дата 22.6.2005, 19:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2074
Регистрация: 4.12.2004

Репутация: 1
Всего: 20



Короче я тему удаляю, ибо я получил ответ на свой вопрос(ламерский), получил на свой и comcon1. Так как сама тема побуждает к флейму её стоит удалить. 
PM MAIL ICQ Skype GTalk Jabber   Вверх
vadims
Дата 22.6.2005, 19:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 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.
PM MAIL   Вверх
comcon1
Дата 22.6.2005, 19:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 838
Регистрация: 11.6.2005
Где: Москва ДАС-МГУ

Репутация: 12
Всего: 17



Хм. Не знал, что в Паскале и С разница такая. Я Паскальный, значить, описал. Ну да ладно - факт тот, что стек реанимируется, и ладно. smile
В репу б тебе поставил, да 100 нету smile


--------------------
PM MAIL   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0565 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.