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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Нужно ли очищать стек при выкидывании Exception ? в рекурсивных функциях, например 
:(
    Опции темы
S.A.P.
Дата 23.10.2005, 21:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

Репутация: 9
Всего: 71



Раньше никогда не обращал внимания, теперь решил разобраться с вопросом.

Допустим имеется код:

Код


struct Overload {
    const char *p;
    Overload( const char *q ) { p = q; }
};

//. . .
 
void f1( int depth )
{
    if ( depth >= 10 ) throw Overload( "f1" );
    f2( depth + 1 );
}

void f2( int depth )
{
    if ( depth >= 10 ) throw Overload( "f2" );
    f3( depth + 1 );
}

void f3( int depth )
{
    if ( depth >= 10 ) throw Overload( "f3" );
    f1( depth + 1 );
}

// . . .

    try {
        f1( 0 );
    }
    catch ( Overload e ) {
        cout << "exception executed in function " << e.p << endl;
    }


Алгоритм действий я как понимаю такой: функции вызывают друг друга, передавая параметр на 1 больше своего, то дех пор, пока одна из функций не получит 10. В таком случае генерируется исключение и управление передается в блок catch.

Если расматривать все на более низком уровне, то очевидно параметры подаются через стек и стек должен восстанавливаться при завершении функции. А что тогда будет в этом случае, ведь ни одна функция фактически не завершиться? Будет ли очищаться стек, либо его надо очищать вручную, либо вобще избегать таких конструкий? Что скажите?

Это сообщение отредактировал(а) Perchilla - 23.10.2005, 21:31
PM MAIL   Вверх
srd
Дата 23.10.2005, 21:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нереварин
**


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

Репутация: 27
Всего: 49



Стек очищается, деструкторы стековых объектов вызываются. Короче, ты ищешь грабли там, где их нет.


--------------------
Не смей читать мою подпись!!!
PM MAIL Jabber   Вверх
S.A.P.
Дата 23.10.2005, 21:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

Репутация: 9
Всего: 71



srd smile .

спасибо,буду знать на будущее smile
PM MAIL   Вверх
Void
Дата 23.10.2005, 22:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



Perchilla
В этом, собственно, и суть исключений (и заодно идиомы RAII) smile


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
S.A.P.
Дата 23.10.2005, 22:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

Репутация: 9
Всего: 71



Кстати, VC 7 исключения обрабатывает очень медленно. Попробуйте вот такую штуку прогнать, не дождетесь smile .
Код

struct Bench_exc {
    int i;
    Bench_exc( int j ) { i = j; };
};

int bench( int i )
{
    if ( i == 20 ) return i+100;
    throw Bench_exc( i+100 );
}

// . . .

   int j;

    for (int i = 0; i < 1000000; ++i) {
        try {
            bench( 10 );
        }
        catch ( Bench_exc e ) {
            j += e.i;
        }
    }


на MinGW - меньше секунды.

Это сообщение отредактировал(а) Perchilla - 23.10.2005, 22:11
PM MAIL   Вверх
Void
Дата 23.10.2005, 22:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λ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
PM MAIL WWW GTalk   Вверх
Helicopterr
Дата 23.10.2005, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 355
Регистрация: 20.8.2005
Где: Stavropol

Репутация: 2
Всего: 3



Пользуясь темой, хочу спросить...
Какова максимальная глубина рекурсии в с++?
И несёт ли использование рекурсии какие-либо опасности типа стек переполнен и др.?



--------------------
people can fly
PM MAIL   Вверх
Void
Дата 23.10.2005, 22:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



Цитата(Helicopterr @ 24.10.2005, 00:32)
Какова максимальная глубина рекурсии в с++?

Зависит от выделенного размера стека smile
Цитата(Helicopterr @ 24.10.2005, 00:32)
И несёт ли использование рекурсии какие-либо опасности типа стек переполнен и др.?

Именно в переполнении стека и заключаются единственные возможные грабли. Поэтому порядок глубины рекурсии для заданного алгоритма крайне желательно знать заранее.


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
Helicopterr
Дата 23.10.2005, 22:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 355
Регистрация: 20.8.2005
Где: Stavropol

Репутация: 2
Всего: 3



Цитата(Void @ 23.10.2005, 22:35)

Зависит от выделенного размера стека smile

а если более конкретно вот например рекурсивный код нахождения факториала-
Код

#include "stdafx.h"

long double recfactorial(short chislo);


int _tmain()
{  
    
    short chislo;
    cin>>chislo;
    cout<<"\nFactorial "<<chislo<<" = "<<recfactorial(chislo);
    return 0;
}
long double recfactorial(short chislo)
{
if(chislo<=1)
return 1;
else
return(chislo*recfactorial(chislo-1));
}




--------------------
people can fly
PM MAIL   Вверх
Void
Дата 24.10.2005, 09:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λ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
PM MAIL WWW GTalk   Вверх
En_t_end
Дата 24.10.2005, 10:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Вопрос в тему... присутсвует кстати в большиснстве тестов по C++.
Для каких обьектов будут вызваны деструкторы при возникновении исключения и обработки его своим catch'ом. Для всех ? Или только для обьктов созданных внутри блока try ?
PM MAIL ICQ Skype GTalk Jabber   Вверх
pablo
Дата 24.10.2005, 11:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 12.2.2005
Где: Вильнюс, Литва

Репутация: 4
Всего: 6



Есть такое явление, называемое "Размотка Стека". Это произходит тогда, когда исключение вознокло в дискрукторе объекта, и небыло перехвачено. Если ф-ция создающая объект глубоко вложена, то размотка приобретает колласальные размеры, и может вызвать трудновыловимые ошибки. Одно из средств предотвращения размотки стека - использование auto_ptr.




--------------------
Первый блин всегда похож на сферу, иногда бывает и куб.
PM MAIL ICQ   Вверх
srd
Дата 24.10.2005, 11:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нереварин
**


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

Репутация: 27
Всего: 49



En_t_end
А пример кода можно? А то я не понял, что именно ты спрашиваешь.


--------------------
Не смей читать мою подпись!!!
PM MAIL Jabber   Вверх
Chaos A.D.
Дата 24.10.2005, 12:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 172
Регистрация: 16.1.2005
Где: 09 RUS

Репутация: 6
Всего: 7



2 pablo

К вопросу о "размотке" стека - если ты о том, что по заморски называется Stack Unwinding, то тут ты ошибаешься. Раскруткой стека (мне это название больше нравится) называется процесс удаления стековых объектов и возврат из вложенных функций до уровня первого попавшегося catch-блока, если он есть конечно. От твоего определения мое отличается тем, что раскрутка стека происходит в любом случае. Если же исключение сгенерировано из деструктора, то это особый случай. Тут, если деструктор, сгегеривший исключение, был вызыван в процессе раскрутки стека, вызывается abort();

Цитата

Одно из средств предотвращения размотки стека - использование auto_ptr


Размотка стека - это Хорошая Вещь, придуманная как часть механизма исключений, и предотвращать её, имхо, довольно глупо.

Это сообщение отредактировал(а) Chaos A.D. - 24.10.2005, 12:11
--------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest
PM MAIL   Вверх
pablo
Дата 24.10.2005, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 12.2.2005
Где: Вильнюс, Литва

Репутация: 4
Всего: 6



2Chaos A.D. Может быть, спасибо что исправил.



--------------------
Первый блин всегда похож на сферу, иногда бывает и куб.
PM MAIL ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

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

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

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

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


 




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


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

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