Re: Обработка ошибок и корректный выход
От: Аноним  
Дата: 01.07.06 22:39
Оценка: 1 (1) +1 -5
Здравствуйте, MBy, Вы писали:

MBy>Привет!


MBy>Пишу на Си. Например, некая ф-ия не смогла что-то выполнить и вернула ошибку. Продолжение выполнения программы стало безсмысленным. Как в таком случае правильнее всего обработать эту ошибку и выйти из программы? При том следует учесть, что необходимо закрыть n-ое количество файлов и вернуть в кучу выделиную память, то есть сделать не выброс а корректное завершение.


А не надо ничего закрывать и память возвращать не надо. Вы же из программы выходите. Виндоуз сам всё вернёт как было.
А корректное завершение можно например так сделать:

exit (1);
Re: Обработка ошибок и корректный выход
От: Pavel Chikulaev Россия  
Дата: 02.07.06 13:50
Оценка: 15 (1) -1
Здравствуйте, MBy, Вы писали:

MBy>Привет!


MBy>Пишу на Си. Например, некая ф-ия не смогла что-то выполнить и вернула ошибку. Продолжение выполнения программы стало безсмысленным. Как в таком случае правильнее всего обработать эту ошибку и выйти из программы? При том следует учесть, что необходимо закрыть n-ое количество файлов и вернуть в кучу выделиную память, то есть сделать не выброс а корректное завершение.


Хорошенько разобись как этого добивается C++, и сделай такое же сам. Тебе хватит стэка автоматических объектов с не тривиальными деструкторами и стэка обработчиков исключений. Ничего сложного сделать этого нет, но как сделаешь, поймешь какой замечательный и главное простой язык C++ И без оверхэда.

ЗЫ. А exit это не вариант.
Re[4]: Обработка ошибок и корректный выход
От: Pavel Chikulaev Россия  
Дата: 03.07.06 14:52
Оценка: 8 (2)
Здравствуйте, Какая разница, Вы писали:

КР>Здравствуйте, Pavel Chikulaev, Вы писали:


PC>>Так, но:

PC>>ISO/IEC 14882:2003 Annex B

КР>Что это за лимиты?


оттуда же
Because computers are finite, C++ implementations are inevitably limited in the size of the programs they
can successfully process. Every implementation shall document those limitations where known. This documentation
may cite fixed limits where they exist, say how to compute variable limits as a function of
available resources, or say that fixed limits do not exist or are unknown.


MSDN: ms-help://MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_vclang/html/f1fa59c6-55b4-414b-80c5-3df72952160d.htm
The C++ standard recommends limits for various language constructs. The following is a list of constructs where the Visual C++ compiler does not implement the recommended limits. The first number is the recommended limit and the second number is the limit implemented by Visual C++:
— Nesting levels of compound statements, iteration control structures, and selection control structures [256] (64).
— Parameters in one macro definition [256] (127).
— Arguments in one macro invocation [256] (127).
— Characters in a character string literal or wide string literal (after concatenation) [65536] (65535).
— Levels of nested class, structure, or union definitions in a single struct-declaration-list [256] (16).
— Member initializers in a constructor definition [6144] (approximately 600, memory dependent, can increase with the /Zm compiler -option).
— Scope qualifications of one identifier [256] (127).
— Nested external specifications [1024] (10).
— Template arguments in a template declaration [1024] (64).


Про atexit ничего не написано, так что как минимум 32 обработчика можно зарегистрировать.
Re[3]: Обработка ошибок и корректный выход
От: _Storm  
Дата: 07.07.06 07:11
Оценка: 1 (1) :)
Здравствуйте, MBy, Вы писали:

MBy>Типа так?

MBy>
MBy>/* ... */
MBy>  SOME_HANDLE handle = NULL;
MBy>  char* str = NULL;

MBy>  if( some_constructor( &handle ) )
MBy>    goto the_end;

MBy>  str = calloc( 16, sizeof(char) );
MBy>  if( str == NULL )
MBy>    goto the_end;

MBy>  if( some_func( handle, str ) )
MBy>    goto the_end;

MBy>the_end:
MBy>  if( handle )
MBy>    some_destructor( handle );
MBy>  if( str )
MBy>    free( str );

MBy>  return;

MBy>/* ... */
MBy>


MBy>Или я не в ту сторону думаю?

MBy>Правда, тут бы ещё коды ошибок добавить для пущей красоты. Ну или хотя бы true/false.

Я бы переписал это так (без goto)

/* ... */
SOME_HANDLE handle = NULL;
char* str = NULL;

do
{
    if( some_constructor( &handle ) )
        break;

    str = calloc( 16, sizeof(char) );
    if( str == NULL )
        break;

    if( some_func( handle, str ) )
        break;
        
} while(false);

if( handle )
    some_destructor( handle );
if( str )
    free( str );

return;

/* ... */
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: Обработка ошибок и корректный выход
От: _Storm  
Дата: 07.07.06 12:59
Оценка: -1 :)
Здравствуйте, Erop, Вы писали:

E>Я правильно понимаю, что do { ... } while( false ); добавлено типа для повышения читабельности?

E>Или какой такой смысл изводить goto в этом месте таким образом?

Правильно, читабельности, а вследствие и уменьшения возможности допустить ошибку в cлучае goto т.к. метку можно случайно не в то место поставить, передвинуть, а вот со скобками уже тяжелее ошибиться, плюс нагляднее смотрится. Эту конструкцию do {...} while(false) уже где-то на рсдн обсуждали.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Обработка ошибок и корректный выход
От: Roman Odaisky Украина  
Дата: 01.07.06 21:35
Оценка: :)
Здравствуйте, MBy, Вы писали:

MBy>Привет!


MBy>Пишу на Си. Например, некая ф-ия не смогла что-то выполнить и вернула ошибку. Продолжение выполнения программы стало безсмысленным. Как в таком случае правильнее всего обработать эту ошибку и выйти из программы? При том следует учесть, что необходимо закрыть n-ое количество файлов и вернуть в кучу выделиную память, то есть сделать не выброс а корректное завершение.


Ручками, ручками! Вариантов есть.

X x;
if(initX(&x))
{
    Y y;
    if(initY(&y))
    {
        ...
        closeY(&y);
    }
    closeX(&x);
}

X x;
if(!initX(&x))
{
    return 0;
}

Y y;
if(!initY(&y))
{
    closeX(&x);
    return 0;
}

...

closeY(&y);
closeX(&x);

Еще можно с goto. По сути как первый вариант, но без вложенности.
До последнего не верил в пирамиду Лебедева.
Re: Обработка ошибок и корректный выход
От: SageMath  
Дата: 02.07.06 20:57
Оценка: +1
Здравствуйте, MBy, Вы писали:

MBy>Привет!


MBy>Пишу на Си. Например, некая ф-ия не смогла что-то выполнить и вернула ошибку. Продолжение выполнения программы стало безсмысленным. Как в таком случае правильнее всего обработать эту ошибку и выйти из программы? При том следует учесть, что необходимо закрыть n-ое количество файлов и вернуть в кучу выделиную память, то есть сделать не выброс а корректное завершение.


Если приложение потом совсем закрывается, то, действительно, виндовс все удалит сам. А если, например, во входных данных для какой-либо функции случилась ошибка, а память уже понавыделять успели, то я бы пользовался goto. Обсуждали как-то с друзьями подобную тему и пришли к этому мнению Много вложенных ифов сильно загромоздят код, а если метки использовать исключительно для корректного освобождения памяти, то почему бы их не использовать?.. Тем более, если приложение на чистом Си.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Make yourself.
Re[4]: Обработка ошибок и корректный выход
От: MBy Украина http://maxim.vuets.name/
Дата: 07.07.06 07:45
Оценка: +1
Здравствуйте, _Storm, Вы писали:

_S>Я бы переписал это так (без goto)


_S>
_S>} while(false);
_S>


Ну точнее, while(0). Дык ведь Си
А в целом понятно. Спасибо. Посмотрим, может кто-то другой вариант предложит
Hoc est simplicissimum!
Обработка ошибок и корректный выход
От: MBy Украина http://maxim.vuets.name/
Дата: 01.07.06 21:24
Оценка:
Привет!

Пишу на Си. Например, некая ф-ия не смогла что-то выполнить и вернула ошибку. Продолжение выполнения программы стало безсмысленным. Как в таком случае правильнее всего обработать эту ошибку и выйти из программы? При том следует учесть, что необходимо закрыть n-ое количество файлов и вернуть в кучу выделиную память, то есть сделать не выброс а корректное завершение.
Hoc est simplicissimum!
Re[2]: Обработка ошибок и корректный выход
От: MBy Украина http://maxim.vuets.name/
Дата: 02.07.06 10:06
Оценка:
Здравствуйте, Аноним, Вы писали:

А>А не надо ничего закрывать и память возвращать не надо. Вы же из программы выходите. Виндоуз сам всё вернёт как было.

А>А корректное завершение можно например так сделать:

А>
А>exit (1);
А>


Вот на счёт exit’а я и думал. Спасибо.
Просто сомнения в плане того, что если я выделил память (malloc и calloc), и не отдал её при выходе (exit) — это не есть хорошо.
Кстати, одной Виндой тут не обойтись
Hoc est simplicissimum!
Re: Обработка ошибок и корректный выход
От: 0xDEADBEEF Ниоткуда  
Дата: 02.07.06 21:04
Оценка:
Здравствуйте, MBy, Вы писали:

MBy>Привет!


MBy>Пишу на Си. Например, некая ф-ия не смогла что-то выполнить и вернула ошибку.

MBy>Продолжение выполнения программы стало безсмысленным.
вызвать exit(<<error code>>)

MBy>Как в таком случае правильнее всего обработать эту ошибку и выйти из программы?

если твоя прога не наплодила своих файлов и не нагадила в другие — вышеописанный способ подходит

MBy>При том следует учесть, что необходимо закрыть n-ое количество файлов и вернуть в кучу

MBy>выделиную память, то есть сделать не выброс а корректное завершение.
И винды и юнихи (включая линух) за нерадивой программой подметут
То есть, можешь выходить ничего за собой не очищая.

Если же ты работаешь под всякими мелкими осями типа symbian или palmos, то сначала почитай доументацию
__________
16.There is no cause so right that one cannot find a fool following it.
Re: Обработка ошибок и корректный выход
От: Socrat Россия  
Дата: 03.07.06 07:29
Оценка:
Здравствуйте, MBy, Вы писали:

MBy>Привет!


MBy>Пишу на Си. Например, некая ф-ия не смогла что-то выполнить и вернула ошибку. Продолжение выполнения программы стало безсмысленным. Как в таком случае правильнее всего обработать эту ошибку и выйти из программы? При том следует учесть, что необходимо закрыть n-ое количество файлов и вернуть в кучу выделиную память, то есть сделать не выброс а корректное завершение.


Это зависит от структуры программы. Если работаешь под виндой, то можно просто послать своему окну команду закрыться.
Re[2]: Обработка ошибок и корректный выход
От: ArtDenis Россия  
Дата: 03.07.06 08:14
Оценка:
Socrat пишет:
> Это зависит от структуры программы. Если работаешь под виндой, то можно просто послать своему окну команду закрыться.

Ну да? И что, при этом закроются все файлы, которые были открыты для
работы с этим окном?
Posted via RSDN NNTP Server 2.0
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[3]: Обработка ошибок и корректный выход
От: Socrat Россия  
Дата: 03.07.06 08:23
Оценка:
Здравствуйте, ArtDenis, Вы писали:

AD>Socrat пишет:

>> Это зависит от структуры программы. Если работаешь под виндой, то можно просто послать своему окну команду закрыться.

AD>Ну да? И что, при этом закроются все файлы, которые были открыты для

AD>работы с этим окном?

Нет. Но если программа написана правильно, в обработке события должно быть прописано закрытие всех файлов.
Re[4]: Обработка ошибок и корректный выход
От: Pavel Chikulaev Россия  
Дата: 03.07.06 08:35
Оценка:
Здравствуйте, Socrat, Вы писали:

S>Здравствуйте, ArtDenis, Вы писали:


AD>>Socrat пишет:

>>> Это зависит от структуры программы. Если работаешь под виндой, то можно просто послать своему окну команду закрыться.

AD>>Ну да? И что, при этом закроются все файлы, которые были открыты для

AD>>работы с этим окном?

S>Нет. Но если программа написана правильно, в обработке события должно быть прописано закрытие всех файлов.

Все мои программы неправильные ( Никогда не пишу закрыть файл RAII рулез.
Re[4]: Обработка ошибок и корректный выход
От: ArtDenis Россия  
Дата: 03.07.06 08:48
Оценка:
Socrat пишет:
> Нет. Но если программа написана правильно, в обработке события должно быть прописано закрытие всех файлов.

Закрытие всех файлов должно быть там, где это необходимо по логике
программы. Закрытие файлов ручками в окном событии — это частный случай
и далеко не самый лучший
Posted via RSDN NNTP Server 2.0
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re: Обработка ошибок и корректный выход
От: Какая разница Украина  
Дата: 03.07.06 14:16
Оценка:
Здравствуйте, MBy, Вы писали:

MBy>Привет!


MBy>Пишу на Си. Например, некая ф-ия не смогла что-то выполнить и вернула ошибку. Продолжение выполнения программы стало безсмысленным. Как в таком случае правильнее всего обработать эту ошибку и выйти из программы? При том следует учесть, что необходимо закрыть n-ое количество файлов и вернуть в кучу выделиную память, то есть сделать не выброс а корректное завершение.


Еще есть вариант посмотреть в сторону функции atexit


Processes the specified function at exit.

int atexit( void ( __cdecl *func )( void ) );


Если открытые файлы хранить в каком то списке и иметь глобальный указатель на этот список то
имхо тогда легко в этой функцими произвести корректное закрытие всех открытых файлов
!0xDEAD
Re[2]: Обработка ошибок и корректный выход
От: Pavel Chikulaev Россия  
Дата: 03.07.06 14:22
Оценка:
Здравствуйте, Какая разница, Вы писали:

КР>Здравствуйте, MBy, Вы писали:


MBy>>Привет!


MBy>>Пишу на Си. Например, некая ф-ия не смогла что-то выполнить и вернула ошибку. Продолжение выполнения программы стало безсмысленным. Как в таком случае правильнее всего обработать эту ошибку и выйти из программы? При том следует учесть, что необходимо закрыть n-ое количество файлов и вернуть в кучу выделиную память, то есть сделать не выброс а корректное завершение.


КР>Еще есть вариант посмотреть в сторону функции atexit



КР>
КР>Processes the specified function at exit.

КР>int atexit( void ( __cdecl *func )( void ) );
КР>


КР>Если открытые файлы хранить в каком то списке и иметь глобальный указатель на этот список то

КР>имхо тогда легко в этой функцими произвести корректное закрытие всех открытых файлов

Так, но:
ISO/IEC 14882:2003 Annex B

The limits may constrain quantities that include those described below or others. The bracketed number
following each quantity is recommended as the minimum for that quantity. However, these quantities are
only guidelines and do not determine compliance.

— Nesting levels of compound statements, iteration control structures, and selection control structures
[256].
— Nesting levels of conditional inclusion [256].
— Pointer, array, and function declarators (in any combination) modifying an arithmetic, structure, union,
or incomplete type in a declaration [256].
— Nesting levels of parenthesized expressions within a full expression [256].
— Number of characters in an internal identifier or macro name [1 024].
— Number of characters in an external identifier [1 024].
— External identifiers in one translation unit [65 536].
— Identifiers with block scope declared in one block [1 024].
— Macro identifiers simultaneously defined in one translation unit [65 536].
— Parameters in one function definition [256].
— Arguments in one function call [256].
— Parameters in one macro definition [256].
— Arguments in one macro invocation [256].
— Characters in one logical source line [65 536].
— Characters in a character string literal or wide string literal (after concatenation) [65 536].
— Size of an object [262 144].
— Nesting levels for #include files [256].
— Case labels for a switch statement (excluding those for any nested switch statements) [16 384].
— Data members in a single class, structure, or union [16 384].
— Enumeration constants in a single enumeration [4 096].
— Levels of nested class, structure, or union definitions in a single struct-declaration-list [256].
— Functions registered by atexit()[32].
— Direct and indirect base classes [16 384].
— Direct base classes for a single class [1 024].
— Members declared in a single class [4 096].
— Final overriding virtual functions in a class, accessible or not [16 384].
— Direct and indirect virtual bases of a class [1 024].
— Static members of a class [1 024].
— Friend declarations in a class [4 096].
— Access control declarations in a class [4 096].
— Member initializers in a constructor definition [6 144].
— Scope qualifications of one identifier [256].
— Nested external specifications [1 024].
— Template arguments in a template declaration [1 024].
— Recursively nested template instantiations [17].
— Handlers per try block [256].
— Throw specifications on a single function declaration [256].

Re[3]: Обработка ошибок и корректный выход
От: Какая разница Украина  
Дата: 03.07.06 14:31
Оценка:
Здравствуйте, Pavel Chikulaev, Вы писали:

PC>Так, но:

PC>ISO/IEC 14882:2003 Annex B

Что это за лимиты?
!0xDEAD
Re[5]: Обработка ошибок и корректный выход
От: Какая разница Украина  
Дата: 03.07.06 14:56
Оценка:
Здравствуйте, Pavel Chikulaev, Вы писали:

PC>Здравствуйте, Какая разница, Вы писали:


КР>>Здравствуйте, Pavel Chikulaev, Вы писали:


PC>>>Так, но:

PC>>>ISO/IEC 14882:2003 Annex B

КР>>Что это за лимиты?

PC>[/q]

PC>Про atexit ничего не написано, так что как минимум 32 обработчика можно зарегистрировать.


А теперь понял тебя

При грамотном дизайне и правильном проектировании достаточно одного обработчика atexit
!0xDEAD
Re[2]: Обработка ошибок и корректный выход
От: MBy Украина http://maxim.vuets.name/
Дата: 03.07.06 18:31
Оценка:
Здравствуйте, Pavel Chikulaev, Вы писали:

PC>Хорошенько разобись как этого добивается C++, и сделай такое же сам.

Ну там больше способов, IMO. Хотя бы те же try/catch/throw

PC>Тебе хватит стэка автоматических объектов с не тривиальными деструкторами и стэка обработчиков исключений. Ничего сложного сделать этого нет, но как сделаешь, поймешь какой замечательный и главное простой язык C++ И без оверхэда.

Не спорю, что хорош. Но задача — писать на Си.

PC>ЗЫ. А exit это не вариант.

Почему?
Hoc est simplicissimum!
Re[2]: Обработка ошибок и корректный выход
От: MBy Украина http://maxim.vuets.name/
Дата: 03.07.06 18:32
Оценка:
Здравствуйте, Socrat, Вы писали:

MBy>>Пишу на Си.


S>Это зависит от структуры программы. Если работаешь под виндой, то можно просто послать своему окну команду закрыться.


Окон нет. Пишу на Си
Hoc est simplicissimum!
Re[2]: Обработка ошибок и корректный выход
От: MBy Украина http://maxim.vuets.name/
Дата: 03.07.06 18:45
Оценка:
Здравствуйте, SageMath, Вы писали:

SM>Если приложение потом совсем закрывается, то, действительно, виндовс все удалит сам. А если, например, во входных данных для какой-либо функции случилась ошибка, а память уже понавыделять успели, то я бы пользовался goto. Обсуждали как-то с друзьями подобную тему и пришли к этому мнению Много вложенных ифов сильно загромоздят код, а если метки использовать исключительно для корректного освобождения памяти, то почему бы их не использовать?.. Тем более, если приложение на чистом Си.


Типа так?
/* ... */
  SOME_HANDLE handle = NULL;
  char* str = NULL;

  if( some_constructor( &handle ) )
    goto the_end;

  str = calloc( 16, sizeof(char) );
  if( str == NULL )
    goto the_end;

  if( some_func( handle, str ) )
    goto the_end;

the_end:
  if( handle )
    some_destructor( handle );
  if( str )
    free( str );

  return;

/* ... */


Или я не в ту сторону думаю?
Правда, тут бы ещё коды ошибок добавить для пущей красоты. Ну или хотя бы true/false.
Hoc est simplicissimum!
Re[2]: Обработка ошибок и корректный выход
От: MBy Украина http://maxim.vuets.name/
Дата: 03.07.06 18:52
Оценка:
Здравствуйте, Какая разница, Вы писали:

КР>Еще есть вариант посмотреть в сторону функции atexit


КР>
КР>Processes the specified function at exit.

КР>int atexit( void ( __cdecl *func )( void ) );
КР>


КР>Если открытые файлы хранить в каком то списке и иметь глобальный указатель на этот список то

КР>имхо тогда легко в этой функцими произвести корректное закрытие всех открытых файлов

И такая мысль была. Пока отказался по причине простоты приложения.
Hoc est simplicissimum!
Re: Обработка ошибок и корректный выход
От: Dair Россия  
Дата: 07.07.06 08:17
Оценка:
Ещё один вариант:


#define FUNCTION_NUM (5)

int do_something1( void )
{
  ...

  if( all_ok )
    return 1;
  else {
    fprintf( stderr, "Error bla-bla-bla\n" );
    return 0;
  }
}

int do_something2( void )
{
  ...
}

...

int do_something5( void )

...

typedef int (*action)();

int main( void )
{
  int ret = 0;

  action handler[FUNCTION_NUM] = { do_something1, do_something2, ..., do_something5 };

  open_files();

  for( int i = 0; i < FUNCTION_NUM; ++i ) {
    if( ! handler[i]() ) {
      ret = 1;
      break;
    }
  }

  close_files();
  
  return ret;
}


Если функции совсем независимы друг от друга, можно break в цикле не делать.
Re[4]: Обработка ошибок и корректный выход
От: Erop Россия  
Дата: 07.07.06 12:43
Оценка:
Здравствуйте, _Storm, Вы писали:

_S>Я бы переписал это так (без goto)


_S>
_S>do
_S>{
...
_S>} while(false);
_S>



Я правильно понимаю, что do { ... } while( false ); добавлено типа для повышения читабельности?
Или какой такой смысл изводить goto в этом месте таким образом?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Обработка ошибок и корректный выход
От: MaximE Великобритания  
Дата: 08.07.06 10:28
Оценка:
MBy wrote:

> Пишу на Си. Например, некая ф-ия не смогла что-то выполнить и вернула

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

exit() или abort(). abort() создаст core file, из которого ты можешь попытаться
узнать, что пошло не так.

> При том следует учесть, что необходимо закрыть n-ое

> количество файлов и вернуть в кучу выделиную память, то есть сделать не
> выброс а корректное завершение.

Все ресурсы будут закрыты за тебя операционной системой, кроме ресурсов с kernel
и filesystem persistency. Ресурсы с kernel persistency на linux: semaphore,
shared memory, message queue; с filesystem: файлы и тому подобное (named pipe,
device nodes, ...).

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 2.0
Re[3]: Обработка ошибок и корректный выход
От: mr_jek  
Дата: 14.07.06 14:31
Оценка:
Здравствуйте, MBy, Вы писали:

MBy>Типа так?

MBy>
MBy>/* ... */
MBy>  SOME_HANDLE handle = NULL;
MBy>  char* str = NULL;

MBy>  if( some_constructor( &handle ) )
MBy>    goto the_end;

MBy>  str = calloc( 16, sizeof(char) );
MBy>  if( str == NULL )
MBy>    goto the_end;

MBy>  if( some_func( handle, str ) )
MBy>    goto the_end;

MBy>the_end:
MBy>  if( handle )
MBy>    some_destructor( handle );
MBy>  if( str )
MBy>    free( str );

MBy>  return;

MBy>/* ... */
MBy>


я думаю так будет проще и понятнее:

  int err = 0;
  char* str = NULL;
  
  err = some_constructor(&handle);
  if (err)     
    goto out_construct_failed;

  str = calloc( 16, sizeof(char) );
  if (!str) {
    err = ENOMEM;
    goto out_mermory;
  }
  err = some_func(handle, str);
  if (err)
    goto out_some_func_failed;

  err = 0;

out_some_func_failed:
    free(str);
out_memory:
  some_destructor( handle )
out_construct_failed:
  return err;
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.