Чистый C, обработка ошибок
Это, а как в C принято обрабатывать ошибки?
Т.е. обычная программа: я открываю всякие ком-порты, сокеты и файлы, что-то с ними пытаюсь делать, затем закрываю. В дельфи/java/C#/Clojure это всегда делается через обработку исключений в виде try-finally/using или чего-то аналогичного, в C++ - RAII, а вот что делать в С? Аналогично, с выводом сообщений об ошибке - try{..}catch(Exception e) {logger.Fatal(e};raise}
Я каждую вызываемую функцию проверяю на адекватность возвращаемого результата и при ошибке вывожу в stderr сообщение и strerror(errno), причем выглядит это достаточно единообразно, чтобы хотелось автоматизировать, но принято ли делать хитрожопые макросы типа CHECKERROR(some_call(),"some_call failed") и из них вываливаться из программы при ошибках?
А, и это - принято ли в C заниматься конкатенацией строк по поводу и без повода? А то, скажем, я привык в простых программах особо не мудрить и при необходимости складывать строки, если нет явных требований к производительности. Например, какая-нибудь дурь типа генерации строковых команд из шаблонов и параметров - тупо поскладывал строки и вернул результат. А в С придется strcat использовать, буфера какие-то объявлять, память выделять, трястись за ее удаление или же писать результат прямо в выходной файл, что вообще tight coupling.
Т.е. обычная программа: я открываю всякие ком-порты, сокеты и файлы, что-то с ними пытаюсь делать, затем закрываю. В дельфи/java/C#/Clojure это всегда делается через обработку исключений в виде try-finally/using или чего-то аналогичного, в C++ - RAII, а вот что делать в С? Аналогично, с выводом сообщений об ошибке - try{..}catch(Exception e) {logger.Fatal(e};raise}
Я каждую вызываемую функцию проверяю на адекватность возвращаемого результата и при ошибке вывожу в stderr сообщение и strerror(errno), причем выглядит это достаточно единообразно, чтобы хотелось автоматизировать, но принято ли делать хитрожопые макросы типа CHECKERROR(some_call(),"some_call failed") и из них вываливаться из программы при ошибках?
А, и это - принято ли в C заниматься конкатенацией строк по поводу и без повода? А то, скажем, я привык в простых программах особо не мудрить и при необходимости складывать строки, если нет явных требований к производительности. Например, какая-нибудь дурь типа генерации строковых команд из шаблонов и параметров - тупо поскладывал строки и вернул результат. А в С придется strcat использовать, буфера какие-то объявлять, память выделять, трястись за ее удаление или же писать результат прямо в выходной файл, что вообще tight coupling.
no subject
где finalizer - функция, подчищающая говно за some_call
(no subject)
(no subject)
(no subject)
no subject
CHECK (AllocateResource1, Fin0) ;
CHECK (AllocateResource2, Fin1) ;
CHECK (AllocateResource3, Fin2) ;
use resources
FreeResource3 ;
Fin2:
FreeResource2 ;
Fin1:
FreeResource1 ;
Fin0:
и макрос
CHECK (func, label) \
if (!func ())
goto label ;
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
no subject
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
no subject
(no subject)
no subject
Особенно забавно это делать на телефонах, когда в любой момент может кончиться память. И тогда надо последовательно освобождать все ресурсы графической подсистемы на данный кадр, а затем кидать в JVM эксепшн "сотонинская жаба, убери мусор".
no subject
Понятно, что не есть это хороший тон, но это специфика работы. В частности, в нашем XML-языке при невозможности что-то сделать на выходе команды генерируется узел с текстом ошибки, но - опять же в "куче". Не хватило место под первый malloc() - так не хватит и на цепочку последующих. И если системе килобайта жалко, то она поставлена не то что на колени, а раком, и даже на логгер особо рассчитывать не приходится. Как бы ни было обидно.
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
no subject
Другое дело, что процесс это достаточно унылый: в силу бедности языка приходится писать много лишнего кода, и контекст восприятия рвется. Но ничего, для сельской местности сойдёт, по мне всяко лучше, чем goto cleanup :)
no subject
no subject
В особо умных исходниках принято. Такой макрос называется ASSERT :)
Но вообще, в сях мудрить не стоит - чем проще, тем лучше. Поэтому, как правило, тупо проверяется каждое возвращаемое значение каждой функции.
"А, и это - принято ли в C заниматься конкатенацией строк по поводу и без повода? А то, скажем, я привык в простых программах особо не мудрить и при необходимости складывать строки, если нет явных требований к производительности. Например, какая-нибудь дурь типа генерации строковых команд из шаблонов и параметров - тупо поскладывал строки и вернул результат. А в С придется strcat использовать, буфера какие-то объявлять, память выделять, трястись за ее удаление или же писать результат прямо в выходной файл, что вообще tight coupling."
Принято, если нет явных требований к производительности :) А вот память выделять без явной необходимости не стоит. Все буфера выделяются статически или в стеке, соответственно и освобождать ничё не требуется. Размер выделяемого буфера, естественно, выбирается эмпирически. А что вы хотели, low level programming.
(no subject)
no subject
no subject
Емнип, там трясуться за производительность, поэтому в линупсах даже придумали writev. Вот куда он потом дополз - вопрос более интересный.
(no subject)
(no subject)
(no subject)
no subject
Ну и тут делайте. setjmp/longjmp
(no subject)
(no subject)
no subject
(no subject)
(no subject)
(no subject)
no subject
(no subject)
(no subject)
no subject
(no subject)
no subject
http://habrahabr.ru/post/141507/
(no subject)
no subject
Ну, если лезть обратно на пальму, то
1]
status = 0;
while (1) {
if ( fail(status = f1()) )
break;
if ( fail(status = f2()) )
break;
status = f3();
break;
}
//зачищаем всех, кто не NULL
2] лестница (MS COM approach)
var lhv1;
status = create1(&lhv1);
if (fail(status)) {
print_error(status);
} else {
//хитрость в том, что dispose пишется сразу.
//статус заверщения - глобален! Привет HRESULT
//здесь в том же формате пишем второй шаг (рекурсия:) ):
var lhv2;
status = create2(&lhv2);
if (fail(status)) {
print_error(status);
} else {
//next step is here
dispose(lhv2)
}
dispose(lhv1)
}
return status.
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
no subject
1) Переименовать исходники в *.cpp
2) use raii
3) PROFIT!!!
С конкатенацией строк, говорят, тоже помогает.
(no subject)
(no subject)
(no subject)
(no subject)
no subject
resource1 = alloc_resource1();
if (resource1) {
resource2 = alloc_resource2();
if (resource2) {
// use resource1 & resource2
free_resource2(resource2);
} else
log("alloc_resource2 failed");
free_resource1(resource1);
} else
log("alloc_resource1 failed");
Единственный большой недостаток - с увеличением количества ресурсов растёт вложенность. Иногда помогает разбиение на более мелкие функции.
Но лучше перестать грызть себе нокти и делать так, как я написал в предыдущем комменте.
no subject
долбо^W можно пользоваться макросом который прыгает за return success где в конце функции в обратном порядке написаны освобождалки ресурсов в нужное место.
Можно иметь и список функций очистки на функцию и вызывать их в обратном порядке. Можно иметь класс (тссс!) строки и конкатенатор к нему. И память выделяемую регионами так чтобы ни одного free в коде не было.
Посмотрите на код тех для кого вы пишете и делайте так же как они - иначе они не примут контрибуции :) Я ж не верю что это себе :D
(no subject)
(no subject)
no subject
(no subject)
(no subject)
no subject
Дешево и сердито. Плюс вариации. Можно, конечно, и exceptions замутить (типа таких (http://www.on-time.com/ddj0011.htm)), но в сборном проекте они не особенно полезны, вот если монолитная система, тогда может быть.
Насчет строк -- или, как сказали,
aprintf
, если есть, или поискать какую-нибудь более развесистую библиотеку.no subject
no subject
no subject
ресурсы освобождать очень просто:
return OK;
fail:
if(res1) free_res(res1);
и так по каждому;
return FAIL;
}
(no subject)