![]() |
Модераторы: Daevaorn |
![]() ![]() ![]() |
|
S.A.P. |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2664 Регистрация: 11.6.2004 Репутация: 9 Всего: 71 |
Раньше никогда не обращал внимания, теперь решил разобраться с вопросом.
Допустим имеется код:
Алгоритм действий я как понимаю такой: функции вызывают друг друга, передавая параметр на 1 больше своего, то дех пор, пока одна из функций не получит 10. В таком случае генерируется исключение и управление передается в блок catch. Если расматривать все на более низком уровне, то очевидно параметры подаются через стек и стек должен восстанавливаться при завершении функции. А что тогда будет в этом случае, ведь ни одна функция фактически не завершиться? Будет ли очищаться стек, либо его надо очищать вручную, либо вобще избегать таких конструкий? Что скажите? Это сообщение отредактировал(а) Perchilla - 23.10.2005, 21:31 |
|||
|
||||
srd |
|
|||
![]() Нереварин ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 951 Регистрация: 30.8.2003 Где: Владивосток Репутация: 27 Всего: 49 |
Стек очищается, деструкторы стековых объектов вызываются. Короче, ты ищешь грабли там, где их нет.
-------------------- Не смей читать мою подпись!!! |
|||
|
||||
S.A.P. |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2664 Регистрация: 11.6.2004 Репутация: 9 Всего: 71 |
srd
![]() спасибо,буду знать на будущее ![]() |
|||
|
||||
Void |
|
|||
![]() λcat.lolcat ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2206 Регистрация: 16.11.2004 Где: Zürich Репутация: 40 Всего: 173 |
Perchilla
В этом, собственно, и суть исключений (и заодно идиомы RAII) ![]() -------------------- “Coming back to where you started is not the same as never leaving.” — Terry Pratchett |
|||
|
||||
S.A.P. |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2664 Регистрация: 11.6.2004 Репутация: 9 Всего: 71 |
Кстати, VC 7 исключения обрабатывает очень медленно. Попробуйте вот такую штуку прогнать, не дождетесь
![]()
на MinGW - меньше секунды. Это сообщение отредактировал(а) Perchilla - 23.10.2005, 22:11 |
|||
|
||||
Void |
|
|||
![]() λcat.lolcat ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2206 Регистрация: 16.11.2004 Где: Zürich Репутация: 40 Всего: 173 |
Perchilla
VC++ реализует исключения с помощью SEH, а MinGW каким-то своим способом. Если взглянуть на результаты GetProcessTimes, то бинарик VC++ бОльшую часть времени проводит в kernel time. Подробности реализации исключений в VC++ расписаны здесь. -------------------- “Coming back to where you started is not the same as never leaving.” — Terry Pratchett |
|||
|
||||
Helicopterr |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 355 Регистрация: 20.8.2005 Где: Stavropol Репутация: 2 Всего: 3 |
Пользуясь темой, хочу спросить...
Какова максимальная глубина рекурсии в с++? И несёт ли использование рекурсии какие-либо опасности типа стек переполнен и др.? -------------------- people can fly |
|||
|
||||
Void |
|
||||
![]() λcat.lolcat ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2206 Регистрация: 16.11.2004 Где: Zürich Репутация: 40 Всего: 173 |
Зависит от выделенного размера стека ![]()
Именно в переполнении стека и заключаются единственные возможные грабли. Поэтому порядок глубины рекурсии для заданного алгоритма крайне желательно знать заранее. -------------------- “Coming back to where you started is not the same as never leaving.” — Terry Pratchett |
||||
|
|||||
Helicopterr |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 355 Регистрация: 20.8.2005 Где: Stavropol Репутация: 2 Всего: 3 |
а если более конкретно вот например рекурсивный код нахождения факториала-
-------------------- people can fly |
||||
|
|||||
Void |
|
|||
![]() λcat.lolcat ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2206 Регистрация: 16.11.2004 Где: Zürich Репутация: 40 Всего: 173 |
Helicopterr
Глубина рекурсии O(N), каждый вызов recfactorial занимает в стеке как минимум sizeof(short) + адрес возврата. Линкер VC++ по умолчанию задает размер стека 1 Мб. Получаем максимально возможную глубину рекурсии порядка 10^5, что все равно выходит за диапазон short (пар-р chislo). -------------------- “Coming back to where you started is not the same as never leaving.” — Terry Pratchett |
|||
|
||||
En_t_end |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2074 Регистрация: 4.12.2004 Репутация: 1 Всего: 20 |
Вопрос в тему... присутсвует кстати в большиснстве тестов по C++.
Для каких обьектов будут вызваны деструкторы при возникновении исключения и обработки его своим catch'ом. Для всех ? Или только для обьктов созданных внутри блока try ? |
|||
|
||||
pablo |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 320 Регистрация: 12.2.2005 Где: Вильнюс, Литва Репутация: 4 Всего: 6 |
Есть такое явление, называемое "Размотка Стека". Это произходит тогда, когда исключение вознокло в дискрукторе объекта, и небыло перехвачено. Если ф-ция создающая объект глубоко вложена, то размотка приобретает колласальные размеры, и может вызвать трудновыловимые ошибки. Одно из средств предотвращения размотки стека - использование auto_ptr.
-------------------- Первый блин всегда похож на сферу, иногда бывает и куб. |
|||
|
||||
srd |
|
|||
![]() Нереварин ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 951 Регистрация: 30.8.2003 Где: Владивосток Репутация: 27 Всего: 49 |
En_t_end
А пример кода можно? А то я не понял, что именно ты спрашиваешь. -------------------- Не смей читать мою подпись!!! |
|||
|
||||
Chaos A.D. |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 172 Регистрация: 16.1.2005 Где: 09 RUS Репутация: 6 Всего: 7 |
2 pablo
К вопросу о "размотке" стека - если ты о том, что по заморски называется Stack Unwinding, то тут ты ошибаешься. Раскруткой стека (мне это название больше нравится) называется процесс удаления стековых объектов и возврат из вложенных функций до уровня первого попавшегося catch-блока, если он есть конечно. От твоего определения мое отличается тем, что раскрутка стека происходит в любом случае. Если же исключение сгенерировано из деструктора, то это особый случай. Тут, если деструктор, сгегеривший исключение, был вызыван в процессе раскрутки стека, вызывается abort();
Размотка стека - это Хорошая Вещь, придуманная как часть механизма исключений, и предотвращать её, имхо, довольно глупо. Это сообщение отредактировал(а) Chaos A.D. - 24.10.2005, 12:11 --------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest |
|||
|
||||
pablo |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 320 Регистрация: 12.2.2005 Где: Вильнюс, Литва Репутация: 4 Всего: 6 |
2Chaos A.D. Может быть, спасибо что исправил.
-------------------- Первый блин всегда похож на сферу, иногда бывает и куб. |
|||
|
||||
En_t_end |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2074 Регистрация: 4.12.2004 Репутация: 1 Всего: 20 |
srd
Some obj; try { Some obj2; } catch(...) { // // // } Для каких обьектов будет вызван деструктор при возникновении исключения ? |
|||
|
||||
srd |
|
|||
![]() Нереварин ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 951 Регистрация: 30.8.2003 Где: Владивосток Репутация: 27 Всего: 49 |
Так как в твоём примере нигде нет инструкции throw, то могу предположить, что исключение бросается внутри конструктора класса Some.
а) Если исключение будет брошено при конструировании объекта obj, то будут вызваны деструкторы для тех объектов-членов, для которых успели отработать конструкторы. Для остальных объектов-членов деструкторы вызваны не будут. Деструктор для самого obj и ob2 тоже вызван не будет. б) Если исключение будет брошено при конструировании obj2, то ни для самого obj, ни для его членов деструкторы не вызовутся. Для obj2 деструктор тоже не будет вызван. Будут вызваны деструкторы только для объектов-членов obj2, для которых успели отработать конструкторы до исключения. -------------------- Не смей читать мою подпись!!! |
|||
|
||||
En_t_end |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2074 Регистрация: 4.12.2004 Репутация: 1 Всего: 20 |
srd
Все верно... |
|||
|
||||
Helicopterr |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 355 Регистрация: 20.8.2005 Где: Stavropol Репутация: 2 Всего: 3 |
возвращает то ф-ция long double а не short. вобщем при использовании рекурсии надо считать сколько в этой функции выделяется памяти под переменные и умножать на предполагаемую глубину рекурсии а затем сравнвать это с 1Мб? И если получилось больше то рекурсию не использовать? И ещё правда, что рекурсия работает более медленно, чем тот же алгоритм, реализованный на циклах? Это сообщение отредактировал(а) Helicopterr - 24.10.2005, 22:42 -------------------- people can fly |
|||
|
||||
Void |
|
||||||||
![]() λcat.lolcat ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2206 Регистрация: 16.11.2004 Где: Zürich Репутация: 40 Всего: 173 |
При чем тут возвращаемое значение? Глубина рекурсии в твоем примере равна chislo - 1.
+ параметры ф-ции. Но точный размер можно узнать, только посмотрев ассемблерный листинг сгенерированного кода.
Вообще говоря, да, но закладываться на это не стоит. Нормально раскрутить в цикл можно только хвостовую рекурсию, для остальных случаев все равно приходиться эмулировать стек вручную, что не особо повышает скорость, но существенно снижает читаемость кода.
Если получилось больше, есть существенная вероятность, что в алгоритме ошибка, или использован неподходящий алгоритм. А производить такие расчеты для каждой рекурсивной ф-ции - имхо, странное занятие. -------------------- “Coming back to where you started is not the same as never leaving.” — Terry Pratchett |
||||||||
|
|||||||||
Helicopterr |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 355 Регистрация: 20.8.2005 Где: Stavropol Репутация: 2 Всего: 3 |
Cпасибо согласен. Однако вроде бы программный стек увеличивается динамически по мере объявления в программе новых переменных, отхватывая динамическую память "куча"? Что за информация об огораничении стека линкером в 1Мб? Это сообщение отредактировал(а) Helicopterr - 24.10.2005, 23:09 -------------------- people can fly |
|||
|
||||
Void |
|
||||||||
![]() λcat.lolcat ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2206 Регистрация: 16.11.2004 Где: Zürich Репутация: 40 Всего: 173 |
Да, это так, но 1 Мб здесь указывает именно на предельный размер, который система позволит выделить. Когда стек превышает указанный при создании потока предел, выбрасывается исключение. P.S. Забавный компилятор VC++ 8.0:
Без комментариев ![]() P.P.S. Впрочем, и за предупреждение тоже - все-таки, нехилый там анализ кода производится. Это сообщение отредактировал(а) Void - 24.10.2005, 23:37 -------------------- “Coming back to where you started is not the same as never leaving.” — Terry Pratchett |
||||||||
|
|||||||||
Helicopterr |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 355 Регистрация: 20.8.2005 Где: Stavropol Репутация: 2 Всего: 3 |
Void
Как вцелом компилятор VC++ 8.0? Лучше 7-го? -------------------- people can fly |
|||
|
||||
![]() ![]() ![]() |
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |