Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Блок try... finally на С++


Автор: Kuvaldis 4.10.2007, 20:10
Всем привет!
Вот возникла у меня необходимость реализации такого блока (такого ключевого слова вроде как нету)
принцип действия блока: управление в finally попадает всегда, даже если были исключения.
Нужно для освобождения ресурсов
Аналогично придумал делать только с метками, но это мягко говоря некрасиво.
Что посоветуете? И интересно, а почему такая возможность не была заложена в язык?

СУВ, Kuvaldis 

Автор: Daevaorn 4.10.2007, 20:15
Цитата(Kuvaldis @  4.10.2007,  21:10 Найти цитируемый пост)
Что посоветуете? И интересно, а почему такая возможность не была заложена в язык?

возможность заложена, называется http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization. При раскрутки стека в момент исключения вываются деструкторы объектов.
PS: finally есть у MS

Автор: Alek86 4.10.2007, 20:22
Цитата(Kuvaldis @  4.10.2007,  20:10 Найти цитируемый пост)
Нужно для освобождения ресурсов


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

Автор: archimed7592 4.10.2007, 21:11
Alek86, эти умные ресурсы и представляют из себя идиому RAII smile.

Автор: maxim1000 4.10.2007, 22:20
ну если уж хочется совсем похоже на try-finally, можно попробовать так:
Код

try
{
    //тут какие-то действия
}
catch(...)
{
    //тут finally-часть
    throw
}

Автор: Daevaorn 4.10.2007, 22:29
Цитата(Kuvaldis @  4.10.2007,  21:10 Найти цитируемый пост)
управление в finally попадает всегда, даже если были исключения.

Цитата(maxim1000 @  4.10.2007,  23:20 Найти цитируемый пост)
ну если уж хочется совсем похоже на try-finally, можно попробовать так:

"всегда" в твой catch(...) не попадешь

Автор: maxim1000 4.10.2007, 23:56
Цитата(Daevaorn @  4.10.2007,  22:29 Найти цитируемый пост)
"всегда" в твой catch(...) не попадешь

честно говоря, опыта с данной конструкцией нет
но, насколько я знаю, она предназначена именно для отлова всех исключений
это не так?

Автор: nickless 5.10.2007, 00:01
maxim1000, 
код в finally выполняется всегда, и когда не было исключений и когда были, а в catch только после исключения.

Автор: archimed7592 5.10.2007, 00:03
Цитата(maxim1000 @  4.10.2007,  23:56 Найти цитируемый пост)
это не так? 

Так. А что если исключения не будет smile?
Суть finally в гарантированной отработке в любых условиях: было исключение, не было исключения, return отработал, управление само по себе до finally дошло...

Автор: Daevaorn 5.10.2007, 00:04
Цитата(maxim1000 @  5.10.2007,  00:56 Найти цитируемый пост)
это не так? 

мы должны попасть туда всегда при выходе из функции.

Автор: maxim1000 5.10.2007, 00:23
а... ступил smile

Автор: SergeCpp 5.10.2007, 08:19
Kuvaldis, а почему Рихтера не читаем?!...

Там же всё разъяснено в деталях

ЧАСТЬ V СТРУКТУРНАЯ ОБРАБОТКА ИСКЛЮЧЕНИЙ 

http://wm-help.net/books-online/print-page/59464/59464-17.html 
http://wm-help.net/books-online/print-page/59464/59464-18.html

Автор: MAKCim 5.10.2007, 08:25
SergeCpp, 
SEH - это решение для конкретной среды

Автор: korbian 5.10.2007, 08:46
а может так?
Код

try
{
    //тут какие-то действия

    // на последок
    throw;
}
catch(...)
{
    //тут finally-часть
    throw
}


Автор: Daevaorn 5.10.2007, 08:58
Цитата(korbian @  5.10.2007,  09:46 Найти цитируемый пост)
а может так?

и что? тоже другое поведение.

Автор: Lazin 5.10.2007, 09:39
Цитата(korbian @  5.10.2007,  08:46 Найти цитируемый пост)

Код

try
{
    //тут какие-то действия
    // на последок
    throw;
}


А что будет если перед вызовом throw; исключений небыло. Ведь throw без параметров просто повторно запускает последнее перехваченное исключение. 

Автор: antropod 5.10.2007, 13:47
А что если попробовать так.
Код

try
{
    // код 

    // освобождение_ресурсов 
}
catch( ... )
{
    // освобождение_ресурсов
    throw;
}

Конечно, дублирование кода = плохо, поэтому можно поступить следующим образом:
Кидать исключение, если все прошло успешно, и обрабатывать во вложенном try..catch:
Код

class all_okay{};

try
{
    try
    {
         printf( "Твой код здесь.\n" );

         throw all_okay;
    }
    catch( ... )
    {
        printf( "Пора освободить ресурсы.\n" );

        throw;
    }
}
catch( all_okay )
{
    printf( "Все супер.\n" );
}
catch( ... )
{
   printf( "Что-то не так...\n" );
}


Автор: Daevaorn 5.10.2007, 16:03
antropod, а не легче RAII использовать и не париться? ;) ты бы ещё longjump использовал smile 

Автор: nickless 5.10.2007, 16:05
Цитата(antropod @  5.10.2007,  12:47 Найти цитируемый пост)
Кидать исключение, если все прошло успешно

Будет медленнее работать, исключения не расчитаны на то, чтобы их всё время кидали smile 

Автор: archimed7592 5.10.2007, 16:08
Цитата(MAKCim @  5.10.2007,  08:25 Найти цитируемый пост)
SEH - это решение для конкретной среды 

Разве SEH отматывает стек? smile

Автор: MAKCim 5.10.2007, 16:48
Цитата(archimed7592 @  5.10.2007,  16:08 Найти цитируемый пост)
Разве SEH отматывает стек?

я про то, что SEH - это платформо-зависимая вещь

Автор: 0lmer 7.10.2007, 06:46
симуляция блока try - finally с помощью #define

http://rsdn.ru/article/cpp/try_finally.xml

Автор: Alek86 7.10.2007, 15:01
ограничение на использование запятых там плохое ((
нельзя функции многие вызвать

Автор: archimed7592 7.10.2007, 18:09
Ещё и такая конструкция(достаточно распространённая, между прочим) облажается(должна вывести "catch finally"):
Код

try
{
    throw 1;
}
catch(...)
{
    cout << "catch ";
}
finally(
    cout << "finally" << endl;
)

Автор: Alek86 7.10.2007, 19:01
с этим дефайном?


Код

#define finally(Saver) \
catch ( ... ) \
{ \
  Saver \
  throw; \
} \
Saver



так же нельзя, два catch(...)

Автор: archimed7592 7.10.2007, 19:43
Цитата(Alek86 @  7.10.2007,  19:01 Найти цитируемый пост)
так же нельзя, два catch(...) 

О чём я и сказал:

Цитата(archimed7592 @  7.10.2007,  18:09 Найти цитируемый пост)
облажается


Автор: Alek86 7.10.2007, 21:15
гы

а как она может быть тогда растпространенной, если она не компилируется? )

Автор: archimed7592 7.10.2007, 21:20
Цитата(Alek86 @  7.10.2007,  21:15 Найти цитируемый пост)
а как она может быть тогда растпространенной, если она не компилируется? ) 

Эта конструкция распространена в языках, поддерживающих finally - там она компилируется и работает.
В С++ finally нет, а этот пример я привёл в подтверждение того, что упомянутое здесь решение через define далеко не самое лучшее(с RAII вообще ничего не сравнится smile).

Автор: akizelokro 10.10.2007, 10:09
Цитата

И интересно, а почему такая возможность не была заложена в язык?


 smile Я обзадумался, обратился к многоуважаемому талмуду достопочтенного мистера Стенли Б.Липпмана...

На мой взгляд, все дело в том, что хронологически C++ механизм exception появился раньше введения finally в других языках и Microsoft реализации (а);

нацеленность на гибкость (б)
С самого начала заложено, что после обработки исключения программа не должна автоматически вызывать terminate, а должна иметь возможность продолжить работу со следующей инструкции за блоком try-catch. Конструкция finally в том виде, в котором она применяется, чаще всего принуждается к уничтожению динамических объектов, освобождению ресурсов (и т.д. по списку), и в этом случае в 99% случаев уже нет смысла говорить о дальнейшем выполнении программы ( или функции). 


Автор: maxim1000 10.10.2007, 10:33
хмм... если уж поразмышлять о причинах отсутствия finally в С++, то мне кажется, что дело, скорее, в наличии там стековых переменных, которые автоматически удаляются с вызовами соответствующих деструкторов при при выходе из блока по return, throw или goto
в Delphi с этим сложнее: более-менее сложных стековых объектов просто нет, а те, что в куче, сами по себе не удаляются (знатоки Delphi, поправьте, если глупости говорю), вот и нужно место, где в любой ситуации можно удалить созданные объекты...

Автор: akizelokro 10.10.2007, 10:51
Здесь, кстати, можно поступить проще. Написать письмо в соответствующий комитет с просьбой ввести finally, а их ответ приписать здесь. (Или порыться в архиве отказных предложений smile ...)

Автор: Daevaorn 10.10.2007, 11:05
Цитата(akizelokro @  10.10.2007,  11:51 Найти цитируемый пост)
Здесь, кстати, можно поступить проще. Написать письмо в соответствующий комитет с просьбой ввести finally, а их ответ приписать здесь. (Или порыться в архиве отказных предложений smile ...) 

тут уже не раз объяснили почему этого нет и не нужно. комитет об этих причинах, будь уверен, догадывается.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)