Когда компилер с++ вызывает ф-цию, он резервирует ей стек:
sub esp, 0x44
после вызова он возвращает указатель обратно.
Вопрос: как он определяет то, на сколько надо сдвинуть стек (почему именно 44?)
Здравствуйте, grapes, Вы писали:
G>Когда компилер с++ вызывает ф-цию, он резервирует ей стек: G>sub esp, 0x44 G>после вызова он возвращает указатель обратно. G>Вопрос: как он определяет то, на сколько надо сдвинуть стек (почему именно 44?)
Здравствуйте, mik1, Вы писали:
G>>Вопрос: как он определяет то, на сколько надо сдвинуть стек (почему именно 44?)
M>ИМХО, объем передаваемых переменных + объем локальных переменных.
То есть он считает число локальных переменных в вызываемой ф-ции? Зачем? Они же не в стеке будут размещаться!
M>>>ИМХО, объем передаваемых переменных + объем локальных переменных.
G>>То есть он считает число локальных переменных в вызываемой ф-ции? Зачем? Они же не в стеке будут размещаться!
M>А где?
Здравствуйте, grapes, Вы писали:
G>>>То есть он считает число локальных переменных в вызываемой ф-ции? Зачем? Они же не в стеке будут размещаться!
M>>А где?
G>Разве не в обычной памяти?
Здравствуйте, grapes, Вы писали:
G>Когда компилер с++ вызывает ф-цию, он резервирует ей стек: G>sub esp, 0x44 G>после вызова он возвращает указатель обратно. G>Вопрос: как он определяет то, на сколько надо сдвинуть стек (почему именно 44?)
И еще — если бы каждая вызываемая ф-ция размещала бы свои локальные переменные в стеке, то он бы просто лопнул — вот когда происходит глубокая рекурсия (ф-я сама себя вызывает) — это и происходит, а чтобы просто ф-ция с большим к-вом лок. пере-х стек перепелнила — такого еще не случалось (на моем веку)
Здравствуйте, grapes, Вы писали:
G>пере-х стек перепелнила — такого еще не случалось (на моем веку)
Счастливый! (Или молодой? )
Переполнение стека — серезная проблема, она существует с самого начала вычислительной техники, ибо стек — это базовая форма хранения данных. Используется кроме всего прочего, из-за огромной скорочти выделения памяти (фактически, она уже выделена, просто указатель сдвигается). Естественно, она виртуальная, других и не бывает на самом деле, просто ее явно обычно не выделяют, поэтому так говорить не принято.
Здравствуйте, grapes, Вы писали:
G>И еще — если бы каждая вызываемая ф-ция размещала бы свои локальные переменные в стеке, то он бы просто лопнул — вот когда происходит глубокая рекурсия (ф-я сама себя вызывает) — это и происходит, а чтобы просто ф-ция с большим к-вом лок. пере-х стек перепелнила — такого еще не случалось (на моем веку)
А попробуй поставить стек 4kb и создать локальный массив элементов так из 8000.
Здравствуйте, grapes, Вы писали:
G>>>Разве не в обычной памяти? MAG>>А что такое "обычная память"? MAG>>Типа "обычного" стирального порошка?
G>Динамически выделяемая
А какого GUI там переменные должны размещаться? Попробуй каждый раз при вызове функции для всех переменных выделять память используя new, а в конце прибивать delete'ом и посмотри быстродействие.
Здравствуйте, grapes, Вы писали:
G>Когда компилер с++ вызывает ф-цию, он резервирует ей стек: G>sub esp, 0x44 G>после вызова он возвращает указатель обратно. G>Вопрос: как он определяет то, на сколько надо сдвинуть стек (почему именно 44?)
Здравствуйте, vasketsov, Вы писали:
V>Здравствуйте, grapes, Вы писали:
G>>пере-х стек перепелнила — такого еще не случалось (на моем веку) V>Счастливый! (Или молодой? ) V>Переполнение стека — серезная проблема, она существует с самого начала вычислительной техники, ибо стек — это базовая форма хранения данных. Используется кроме всего прочего, из-за огромной скорочти выделения памяти (фактически, она уже выделена, просто указатель сдвигается). Естественно, она виртуальная, других и не бывает на самом деле, просто ее явно обычно не выделяют, поэтому так говорить не принято.
На платформах IBM PC обычно (т.е. в Win) весь стек нити сразу оказывается в виртуальном адресном пространстве процесса. Причем старшая по адресу незаполненная страница памяти имеет флаг PAGE_GUARD, а все остальные незаполненные страницы так вообще процессу не доступны (Access violation), физическая память для них еще не выделена. Когда происходит первое обращение к этой старшей странице, вызывается обработчик, который делает эту страницу доступной, выделяет следующую страницу с младшим адресом и на нее ставит флаг PAGE_GUARD. Этот обработчик можно даже перепрограммировать, но я не пробовал.
Интересно поисследовать, каковы потери в быстродействии из-за этого обработчика.
Интересно, что memcpy заполняет память от младших адресов к старшим. Но вот при использовании ее в конструкторе копирования больших (в несколько страниц) объектов на стеке все работает без Access violation. То есть, прежде чем такой конструктор вызовется, все необходимые страницы памяти под локальные переменные уже будут созданы! Это тоже потеря быстродействия?
Здравствуйте, grapes, Вы писали:
G>Когда компилер с++ вызывает ф-цию, он резервирует ей стек: G>sub esp, 0x44 G>после вызова он возвращает указатель обратно. G>Вопрос: как он определяет то, на сколько надо сдвинуть стек (почему именно 44?)
если я не ошибабсь, компилятор оставляет специальное пространство для проверки, нет ли нарушей границ стека, причем инициализирует специальными символами.
Здравствуйте, ilnar, Вы писали:
I>если я не ошибабсь, компилятор оставляет специальное пространство для проверки, нет ли нарушей границ стека, причем инициализирует специальными символами.
Абсолютно верно.
Стек он забивает 0xCC, а после вызова ф-ции смещает указатель стека назад и смотрит, равен ли он тому, что было до вызова
Здравствуйте, Валерий Б., Вы писали:
ВБ>а все остальные незаполненные страницы так вообще процессу не доступны (Access violation), физическая память для них еще не выделена.
Здесь обычно используется термин "передача", а не "выделение".
ВБ>Этот обработчик можно даже перепрограммировать, но я не пробовал.
Примеры этого есть.
ВБ>Интересно поисследовать, каковы потери в быстродействии из-за этого обработчика.
Никто не запрещает сразу "закоммитить" весь стек.
В этом случае, кстати, последняя страница сторожевой не будет.
Здравствуйте, Валерий Б., Вы писали:
>использовании ее в конструкторе копирования больших (в несколько страниц) объектов на стеке все работает без Access violation. То есть, прежде чем такой конструктор вызовется, все необходимые страницы памяти под локальные переменные уже будут созданы! Это тоже потеря быстродействия?
А ты (ради интереса) посмотри, что компилятор делает, когда размер локальных переменных переваливает через 4кб
А после этого можно будет поспорить по поводу того, что всегда ли "динамическое" выделение памяти будет медленне "стэкового"