Здравствуйте, MBy, Вы писали:
MBy>Привет!
MBy>Пишу на Си. Например, некая ф-ия не смогла что-то выполнить и вернула ошибку. Продолжение выполнения программы стало безсмысленным. Как в таком случае правильнее всего обработать эту ошибку и выйти из программы? При том следует учесть, что необходимо закрыть n-ое количество файлов и вернуть в кучу выделиную память, то есть сделать не выброс а корректное завершение.
А не надо ничего закрывать и память возвращать не надо. Вы же из программы выходите. Виндоуз сам всё вернёт как было.
А корректное завершение можно например так сделать:
Здравствуйте, MBy, Вы писали:
MBy>Привет!
MBy>Пишу на Си. Например, некая ф-ия не смогла что-то выполнить и вернула ошибку. Продолжение выполнения программы стало безсмысленным. Как в таком случае правильнее всего обработать эту ошибку и выйти из программы? При том следует учесть, что необходимо закрыть n-ое количество файлов и вернуть в кучу выделиную память, то есть сделать не выброс а корректное завершение.
Хорошенько разобись как этого добивается C++, и сделай такое же сам. Тебе хватит стэка автоматических объектов с не тривиальными деструкторами и стэка обработчиков исключений. Ничего сложного сделать этого нет, но как сделаешь, поймешь какой замечательный и главное простой язык C++ И без оверхэда.
Здравствуйте, Какая разница, Вы писали:
КР>Здравствуйте, 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 обработчика можно зарегистрировать.
Здравствуйте, Erop, Вы писали:
E>Я правильно понимаю, что do { ... } while( false ); добавлено типа для повышения читабельности? E>Или какой такой смысл изводить goto в этом месте таким образом?
Правильно, читабельности, а вследствие и уменьшения возможности допустить ошибку в cлучае goto т.к. метку можно случайно не в то место поставить, передвинуть, а вот со скобками уже тяжелее ошибиться, плюс нагляднее смотрится. Эту конструкцию do {...} while(false) уже где-то на рсдн обсуждали.
Здравствуйте, 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. По сути как первый вариант, но без вложенности.
Здравствуйте, MBy, Вы писали:
MBy>Привет!
MBy>Пишу на Си. Например, некая ф-ия не смогла что-то выполнить и вернула ошибку. Продолжение выполнения программы стало безсмысленным. Как в таком случае правильнее всего обработать эту ошибку и выйти из программы? При том следует учесть, что необходимо закрыть n-ое количество файлов и вернуть в кучу выделиную память, то есть сделать не выброс а корректное завершение.
Если приложение потом совсем закрывается, то, действительно, виндовс все удалит сам. А если, например, во входных данных для какой-либо функции случилась ошибка, а память уже понавыделять успели, то я бы пользовался goto. Обсуждали как-то с друзьями подобную тему и пришли к этому мнению Много вложенных ифов сильно загромоздят код, а если метки использовать исключительно для корректного освобождения памяти, то почему бы их не использовать?.. Тем более, если приложение на чистом Си.
Пишу на Си. Например, некая ф-ия не смогла что-то выполнить и вернула ошибку. Продолжение выполнения программы стало безсмысленным. Как в таком случае правильнее всего обработать эту ошибку и выйти из программы? При том следует учесть, что необходимо закрыть n-ое количество файлов и вернуть в кучу выделиную память, то есть сделать не выброс а корректное завершение.
Здравствуйте, Аноним, Вы писали:
А>А не надо ничего закрывать и память возвращать не надо. Вы же из программы выходите. Виндоуз сам всё вернёт как было. А>А корректное завершение можно например так сделать:
А>
А>exit (1);
А>
Вот на счёт exit’а я и думал. Спасибо.
Просто сомнения в плане того, что если я выделил память (malloc и calloc), и не отдал её при выходе (exit) — это не есть хорошо.
Кстати, одной Виндой тут не обойтись
Здравствуйте, 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.
Здравствуйте, MBy, Вы писали:
MBy>Привет!
MBy>Пишу на Си. Например, некая ф-ия не смогла что-то выполнить и вернула ошибку. Продолжение выполнения программы стало безсмысленным. Как в таком случае правильнее всего обработать эту ошибку и выйти из программы? При том следует учесть, что необходимо закрыть n-ое количество файлов и вернуть в кучу выделиную память, то есть сделать не выброс а корректное завершение.
Это зависит от структуры программы. Если работаешь под виндой, то можно просто послать своему окну команду закрыться.
Здравствуйте, ArtDenis, Вы писали:
AD>Socrat пишет: >> Это зависит от структуры программы. Если работаешь под виндой, то можно просто послать своему окну команду закрыться.
AD>Ну да? И что, при этом закроются все файлы, которые были открыты для AD>работы с этим окном?
Нет. Но если программа написана правильно, в обработке события должно быть прописано закрытие всех файлов.
Здравствуйте, Socrat, Вы писали:
S>Здравствуйте, ArtDenis, Вы писали:
AD>>Socrat пишет: >>> Это зависит от структуры программы. Если работаешь под виндой, то можно просто послать своему окну команду закрыться.
AD>>Ну да? И что, при этом закроются все файлы, которые были открыты для AD>>работы с этим окном?
S>Нет. Но если программа написана правильно, в обработке события должно быть прописано закрытие всех файлов.
Все мои программы неправильные ( Никогда не пишу закрыть файл RAII рулез.
Socrat пишет: > Нет. Но если программа написана правильно, в обработке события должно быть прописано закрытие всех файлов.
Закрытие всех файлов должно быть там, где это необходимо по логике
программы. Закрытие файлов ручками в окном событии — это частный случай
и далеко не самый лучший
Здравствуйте, MBy, Вы писали:
MBy>Привет!
MBy>Пишу на Си. Например, некая ф-ия не смогла что-то выполнить и вернула ошибку. Продолжение выполнения программы стало безсмысленным. Как в таком случае правильнее всего обработать эту ошибку и выйти из программы? При том следует учесть, что необходимо закрыть n-ое количество файлов и вернуть в кучу выделиную память, то есть сделать не выброс а корректное завершение.
Еще есть вариант посмотреть в сторону функции atexit
Processes the specified function at exit.
int atexit( void ( __cdecl *func )( void ) );
Если открытые файлы хранить в каком то списке и иметь глобальный указатель на этот список то
имхо тогда легко в этой функцими произвести корректное закрытие всех открытых файлов
Здравствуйте, Какая разница, Вы писали:
КР>Здравствуйте, 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].
Здравствуйте, Pavel Chikulaev, Вы писали:
PC>Здравствуйте, Какая разница, Вы писали:
КР>>Здравствуйте, Pavel Chikulaev, Вы писали:
PC>>>Так, но: PC>>>ISO/IEC 14882:2003 Annex B
КР>>Что это за лимиты? PC>[/q]
PC>Про atexit ничего не написано, так что как минимум 32 обработчика можно зарегистрировать.
А теперь понял тебя
При грамотном дизайне и правильном проектировании достаточно одного обработчика atexit
Здравствуйте, Pavel Chikulaev, Вы писали:
PC>Хорошенько разобись как этого добивается C++, и сделай такое же сам.
Ну там больше способов, IMO. Хотя бы те же try/catch/throw
PC>Тебе хватит стэка автоматических объектов с не тривиальными деструкторами и стэка обработчиков исключений. Ничего сложного сделать этого нет, но как сделаешь, поймешь какой замечательный и главное простой язык C++ И без оверхэда.
Не спорю, что хорош. Но задача — писать на Си.
PC>ЗЫ. А exit это не вариант.
Почему?
Здравствуйте, Socrat, Вы писали:
MBy>>Пишу на Си.
S>Это зависит от структуры программы. Если работаешь под виндой, то можно просто послать своему окну команду закрыться.
Здравствуйте, SageMath, Вы писали:
SM>Если приложение потом совсем закрывается, то, действительно, виндовс все удалит сам. А если, например, во входных данных для какой-либо функции случилась ошибка, а память уже понавыделять успели, то я бы пользовался goto. Обсуждали как-то с друзьями подобную тему и пришли к этому мнению Много вложенных ифов сильно загромоздят код, а если метки использовать исключительно для корректного освобождения памяти, то почему бы их не использовать?.. Тем более, если приложение на чистом Си.
Здравствуйте, Какая разница, Вы писали:
КР>Еще есть вариант посмотреть в сторону функции atexit
КР>
КР>Processes the specified function at exit.
КР>int atexit( void ( __cdecl *func )( void ) );
КР>
КР>Если открытые файлы хранить в каком то списке и иметь глобальный указатель на этот список то КР>имхо тогда легко в этой функцими произвести корректное закрытие всех открытых файлов
И такая мысль была. Пока отказался по причине простоты приложения.
Здравствуйте, _Storm, Вы писали:
_S>Я бы переписал это так (без goto)
_S>
_S>do
_S>{
...
_S>} while(false);
_S>
Я правильно понимаю, что do { ... } while( false ); добавлено типа для повышения читабельности?
Или какой такой смысл изводить goto в этом месте таким образом?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
MBy wrote:
> Пишу на Си. Например, некая ф-ия не смогла что-то выполнить и вернула > ошибку. Продолжение выполнения программы стало безсмысленным. Как в > таком случае правильнее всего обработать эту ошибку и выйти из > программы?
exit() или abort(). abort() создаст core file, из которого ты можешь попытаться
узнать, что пошло не так.
> При том следует учесть, что необходимо закрыть n-ое > количество файлов и вернуть в кучу выделиную память, то есть сделать не > выброс а корректное завершение.
Все ресурсы будут закрыты за тебя операционной системой, кроме ресурсов с kernel
и filesystem persistency. Ресурсы с kernel persistency на linux: semaphore,
shared memory, message queue; с filesystem: файлы и тому подобное (named pipe,
device nodes, ...).