2009-06-04 1 views
2

я думал о трудности возникли с обработкой ошибок C .. как кто на самом деле делаетИспользование функции обратного вызова для обработки ошибок в C

if(printf("hello world")==-1){exit(1);} 

Но вы нарушите общих стандартов, не делая таких многословным, и, как правило, бесполезно кодирование. Что ж, если у вас есть обертка вокруг libc? как так что вы могли бы сделать что-то вроде ..

//main... 
error_catchall(my_errors); 
printf("hello world"); //this will automatically call my_errors on an error of printf 
ignore=1; //this makes it so the function will return like normal and we can check error values ourself 
if(fopen.... //we want to know if the file opened or not and handle it ourself. 
} 

int my_errors(){ 
    if(ignore==0){ 
     _exit(1); //exit if we aren't handling this error by flagging ignore 
    } 
return 0; 
//this is called when there is an error anywhere in the libc 
} 
... 

Я рассматриваю возможность сделать такую ​​обертку, как я синтезирование собственного BSD лицензированного Libc (так что я уже должен коснуться неприкасаемым ..), но я хотел бы знать, что люди думают об этом .. будет ли это работать в реальной жизни и быть более полезным, чем возвращение -1?

+0

Проверка на printf (...) == -1 не полезна, так как printf (...) возвращает количество напечатанных символов и не может быть меньше 0. – Kai

+1

«Количество напечатанных символов возвращается . Если произошла ошибка, возвращается -1. " – Earlz

+0

Вы имеете в виду, что все функции libc завернуты, чтобы перейти к параметрам error_catchall в случае ошибки? – LB40

ответ

1

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

Для этого вам понадобятся две версии каждой функции. Один, который захватил ошибки, и один возвращает ошибки.

Я сделал что-то подобное давно, не изменяя библиотеку. Я просто создал функции обертки для обычных вызовов, которые выполняли проверку ошибок. Таким образом, мой вызов errchk_malloc проверил возврат и поднял ошибку, если сбой распределения. Затем я использовал эту версию везде вместо встроенного malloc.

2

в течение этого года я видел несколько попыток мимике попытаться/поймать в ANSI C:

Я думаю, что попробовать/поймать подход является более простым, чем ваш.

+2

Вместо использования таких фреймворков также можно просто использовать простой goto. Вот пример: #define TRY/* ничего */ #define CATCH (ярлык) метка: #define ХОДА (ярлык) Гото метка TRY { FD = открыт (...); if (fd <0) THROW (open_failed); ... } возвращение; CATCH (open_failed) { ... } Это не масштабируется, и на самом деле я бы не рекомендовал такие макросы, но дело в том, что можно использовать goto для обработки ошибок почти так же, как вы используете исключения , хотя goto ограничено одной функцией, поэтому вы не можете передать ее вызывающей функции. – hlovdal

+2

Ваш комментарий может быть озаглавлен «goto считается полезным» :) – dfa

+2

Да;) По-моему, goto недостаточно используется, и я часто рекомендую людям начать использовать его для обработки ошибок. – hlovdal

0

Если цель состоит в том, чтобы выйти с чистой скоростью, как только вы столкнетесь с ошибкой, это нормально ... но если вы хотите сделать минимум восстановления ошибок, я не вижу, как ваш подход полезен ...

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

0

ли вам действительно хотят изменить стандарт поведение вашего LIBC? Вы можете добавить несколько расширений вокруг общих функций.

Например, Gnome использует g_malloc и g_try_malloc. Первый будет прерван при сбое, а позже просто даст нулевой указатель, например malloc.