Может для кого-то это очевидно, но я раньше мучался этой проблемой.
Суть в том, что когда в функции создаются несколько обьектов, выделяется для них память.
И вдруг возникает какая либо неприятность (памяти не хватило, файла нет и т.п. )
Нужно корретно выйти из функции, осободив все ранее созданные обьекты.
По моему это не очень красивый и надежный метод. Елементарно можно забыть где-нибудь поставить free(..)
Много разных идей было как сделать "красивый" и надежный код.
И вот осенило — нужно вкусить "запретный плод" — goto
До этого свято веря, что все можно сделать и без него, даже елегантнее.
M>Я это написал, потому-что может это кому-нибудь будет полезным. M>Может кто-то предложит такой-же эффективный метод, но без goto?
M> M>А еще goto классно работает когда нужно быстро выйти из функции при этом что-то выполнив на последок
M>Главное не переуседствовать и не тыкать goto без везких оснований...
M>Истина всегда где-то посередине.
филосов
истина лежит в использовании, к примеру, std::auto_ptr
Здравствуйте, ssm, Вы писали:
ssm>истина лежит в использовании, к примеру, std::auto_ptr
Все он правильно говорит, это же С, а не С++, а форум у нас по С/С++, а не только по С++.
Другое дело, что ничего нового сказано не было, все и так на С этим пользуются :)))
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, ssm, Вы писали:
ssm>>истина лежит в использовании, к примеру, std::auto_ptr
J>Все он правильно говорит, это же С, а не С++, а форум у нас по С/С++, а не только по С++. J>Другое дело, что ничего нового сказано не было, все и так на С этим пользуются
оно то конечно, с одной стороны, — да, если судить по названию форума,
но с другой, если судить по описанию /*Программирование на C++. No VCL, no MFC, pure C++ only.*/ то скорее всего, что — нет
M>Нужно корретно выйти из функции, осободив все ранее созданные обьекты. <...> M>Елементарно можно забыть где-нибудь поставить free(..) M>Много разных идей было как сделать "красивый" и надежный код. И вот осенило — нужно вкусить "запретный плод" — goto
если говорить о C то можно использовать __try __finally
MSG* new_msg(..)
{
MSG* msg = NULL;
HEADER* header = NULL;
ADDR* to = NULL;
ADDR* from = NULL;
char* body = NULL;
__try
{
header = (HEADER*) malloc( sizeof(HEADER) );
if (header == NULL)
__leave;
...
to = (ADDR*)malloc( sizeof(ADDR) );
if (to == NULL)
__leave;
...
from = (ADDR*)malloc( sizeof(ADDR) );
if (from == NULL)
__leave;
...
msg = (ADDR*)malloc( sizeof(MSG) );
if (msg == NULL)
__leave;
...
}
__finally
{
if (body) free( body ); // !!!if (from) free( from ); // !!!if (to) free( to ); // !!!if (header) free( header ); // !!!
}
}
P.S. я не знаю, __try __finally (__except) стандарт С?
Re[3]: Выход из функции при ошибке
От:
Аноним
Дата:
26.12.02 11:30
Оценка:
Здравствуйте, jazzer, Вы писали:
J>Все он правильно говорит, это же С, а не С++, а форум у нас по С/С++, а не только по С++. J>Другое дело, что ничего нового сказано не было, все и так на С этим пользуются
Я даже C99 стандарт просмотрел — никаких try, finally — чего-то подобного.
Может плохо смотрел.
Может в других клонах чистого С кто видел ?
Здравствуйте, Аноним, Вы писали:
А>Я даже C99 стандарт просмотрел — никаких try, finally — чего-то подобного. А>Может плохо смотрел. А>Может в других клонах чистого С кто видел ?
__try — __finally вещь очень удобная, но в стандарте этого нет, т.к. это
Microsoft Specific —>
The try-finally statement is a Microsoft extension to the C and C++ languages that enables 32-bit target applications to guarantee execution of cleanup code when execution of a block of code is interrupted. Cleanup consists of such tasks as deallocating memory, closing files, and releasing file handles. The try-finally statement is especially useful for routines that have several places where a check is made for an error that could cause premature return from the routine.
For more information on structured exception handling in general, see Exception Handling Topics (SEH).
Гоуту не просто так в игнор записали. Если памяти не хватило, то уже
без разницы когда проверять выделена она или нет. Т.е. все проверки
после всех выделений памяти спасут программера от пользования этим
страшным оператором.
Здравствуйте, jazzer, Вы писали:
J>Другое дело, что ничего нового сказано не было, все и так на С этим пользуются
Я тоже так думал, но устаю видеть как программисты пишут такие конструкции.
Бывает, что дублируется по 10 строчек кода от условия к условию.
И это каким-то чудом проходит испекции кода
Здравствуйте, vav, Вы писали:
vav>А разве это не классический пример выгоды использования умных указателей?
Возможно. Я слабо представляю себе как их можно использовать?
Я говорю не только про выделение памяти, это может быть любой ресурс (файл, сокет и т.п.).
try
{
// здесь получаем ресурсы
ptr = new char[256];
}catch(...)// или конкретный тип исключения
{
if(ptr != null)delete ptr;
// Для других типов ресурсов аналогично
}
Можно также использовать в более сложных ситуациях ещё и __try{} __finaly( Разширения от МелкоСофта ), но это только в крайних случаях и должно быть соответственно оправдано, у меня по крайней мере таких потребностей не возникало.
try
{
// здесь получаем ресурсы
ptr = new char[256];
}catch(...)// или конкретный тип исключения
{
if(ptr != null)delete ptr;
// Для других типов ресурсов аналогично
}
А для CreateFile(..) или fopen(..) тоже будут генерироваться исключения?
Здравствуйте, menify, Вы писали:
M>Здравствуйте, vav, Вы писали:
vav>>А разве это не классический пример выгоды использования умных указателей? M>Возможно. Я слабо представляю себе как их можно использовать?
M>Я говорю не только про выделение памяти, это может быть любой ресурс (файл, сокет и т.п.).
Здравствуйте, menify, Вы писали:
M>Здравствуйте, Stoune:
M>
M>try
M>{
M> // здесь получаем ресурсы
M> ptr = new char[256];
M>}catch(...)// или конкретный тип исключения
M>{
M> if(ptr != null)delete ptr;
M>
Проверку на NULL можно убрать. M>
M>// Для других типов ресурсов аналогично
M>}
M>
M>А для CreateFile(..) или fopen(..) тоже будут генерироваться исключения? M>
Можно проверить код возврата и в случае ошибки сгенерировать исключение.
При частом использовании таких ресурсов лучше сделать класс-обертку, в конструкторе которого выделяется ресурс (открывается файл), а в деструкторе — освобождается.
Хорошая статья на тему Resource management.