Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > оповещение об ошибках в C, кто как делает?


Автор: kosmonaFFFt 19.6.2012, 18:44
Доброго времени суток...

Пишу небольшую библиотеку на C, и никак не могу придумать хороший и удобный, кроссплатформенный и единообразный способ оповещения об ошибках (привычных мне исключений нету ведь)... Собственно прошу поделиться опытом, кто-как делает, стоит ли использовать что-то наподобие libexcept и т. д.

Собственно тут что получается - если всегда возвращать код ошибки/успеха, то неудобно пользоваться функциями, что-то возвращающими, если делать доп. параметр, то не всегда удобно их игнорировать...

В общем пытаюсь найти золотую середину, но пока не могу...

Заранее спасибо...

Автор: 500mhz 19.6.2012, 20:43
Ну во есть такая фигня как регистр флагов, через него можно возвращать ненавязчиво состояние функ

Автор: borisbn 19.6.2012, 20:49
а мне понравилось как в WinAPI (тфу-тьфу-тьфу, сгинь) - делать ф-цию типа GetLastError:
Код

char global_error_string[ много ];
bool /* или bool тоже нет в Си??? */ foo() {
    if ( всё OK ) {
        ...
        return true;
    }
    else {
        strncpy( global_error_string, sizeof( global_error_string ), "Всё плохо" );
        return false;
    }
    return ХЗ;
}

const /* а это то хоть есть ? */ char * what_the_fk() {
    return global_error_string;
}

...
if ( ! foo() ) {
    printf( "%s\n", what_the_fk() );
}

Автор: volatile 19.6.2012, 23:38
Цитата(kosmonaFFFt @  19.6.2012,  18:44 Найти цитируемый пост)
привычных мне исключений нету ведь

Можно организовать нечто очень похожее на исключения.
смотрите стандартные функции: setjmp (), longjmp (), и т.д.


Автор: kosmonaFFFt 20.6.2012, 05:48
Цитата(borisbn @  20.6.2012,  00:49 Найти цитируемый пост)
а мне понравилось как в WinAPI (тфу-тьфу-тьфу, сгинь) - делать ф-цию типа GetLastError:

А как у этого метода с потокобезопасностью? Если например две функции, вызванные параллельно выдадут ошибку одновременно?


Цитата(volatile @  20.6.2012,  03:38 Найти цитируемый пост)
Можно организовать нечто очень похожее на исключения.
смотрите стандартные функции: setjmp (), longjmp (), и т.д.

Ага, даже нашел несколько библиотек, реализующих "исключения", например http://sourceforge.net/projects/libexcept/, но есть сомнения, не вызовет ли это еще больше багов, как будут обрабатываться непойманные "исключения" и т. д. Если знаете какие-нибудь надежные существующие решения под некопилефт лицензиями (Apache, MIT, BSD, WTFPL, и т. д.), был бы рад про них узнать...

UPD.
Так же интересуют способы получения стектрейсов в случае ошибки...

Автор: borisbn 20.6.2012, 08:24
Цитата(kosmonaFFFt @  20.6.2012,  05:48 Найти цитируемый пост)
А как у этого метода с потокобезопасностью? 

Никак. Этого не было в задании )))
Я, вообще-то, думал, что ты переходишь на Си, потому, что нужно писать на какой-нить контроллер, а там, обычно, у процессора одно ядро и несколько потоков только замедлят работу.

Цитата(kosmonaFFFt @  20.6.2012,  05:48 Найти цитируемый пост)
Так же интересуют способы получения стектрейсов в случае ошибки...

http://www.codeproject.com/Articles/11132/Walking-the-callstack
замечательная штука, но Windows/Linux only. Там, правда, на Си++, но это только обёртка. Её можно "снять" и получишь на Си

Автор: kosmonaFFFt 20.6.2012, 08:30
Нет, это не для контроллера... Изначально забыл написать про многопоточность, но очень вероятно выполнение всей этой байды, которую я потихоньку пишу, в многопоточной среде, соответственно всякие глобальные переменные и прочее отпадает, а как красиво сделать без них я пока не придумал...

Добавлено через 2 минуты и 21 секунду
Цитата(borisbn @  20.6.2012,  12:24 Найти цитируемый пост)
замечательная штука, но Windows/Linux only.

Похоже вообще только Windows-only

Автор: math64 20.6.2012, 09:04
Если только для Windows - OuputDebugString() + утилита DebugView для просмотра (скачивается с сайта microsoft.com)

Автор: kosmonaFFFt 20.6.2012, 09:19
Цитата(math64 @  20.6.2012,  13:04 Найти цитируемый пост)
Если только для Windows - OuputDebugString() + утилита DebugView для просмотра (скачивается с сайта microsoft.com) 


Спасибо, но интересуют только кроссплатформенные решения...

Автор: borisbn 20.6.2012, 09:33
Цитата(kosmonaFFFt @  20.6.2012,  08:30 Найти цитируемый пост)
Похоже вообще только Windows-only 

упс... пардон. у меня, просто,  водном каталоге лежал StackWalker и ещё одна приблуда (call_stack_gcc.cpp и call_stack_msvc.cpp)
Прикрепляю архив

Автор: kosmonaFFFt 20.6.2012, 13:45
Хм, спасибо, штука интересная, может попробую использовать...

Автор: xvr 20.6.2012, 14:51
Цитата(kosmonaFFFt @  19.6.2012,  18:44 Найти цитируемый пост)
Пишу небольшую библиотеку на C, и никак не могу придумать хороший и удобный, кроссплатформенный и единообразный способ оповещения об ошибках

В библиотеке делаете указатель на функцию, которая быдет вызываться библиотекой в случае ошибки. По умолчанию там стоит заглушка (пустая функция). Указатель может инициализировать пользователь библиотеки своей функцией (а уж в ней делать что хочет - ругаться в консоль, убивать программу или делать аналог exception'ов через setjmp/longjmp)

После возврата из этой функции библиотека осуществляет действие по умолчанию - для нефатальных ошибок молча их игнорирует, для фатальных - аварийно завершает работу

Автор: kosmonaFFFt 20.6.2012, 15:06
Тоже над этим вариантом думал, но непонятно как быть с многопоточностью... Указатель то на коллбэк всего один...

Автор: xvr 20.6.2012, 15:15
Цитата(kosmonaFFFt @  20.6.2012,  15:06 Найти цитируемый пост)
но непонятно как быть с многопоточностью... Указатель то на коллбэк всего один...

Для этого есть thread-local переменные. Они есть на всех платформах, но синтаксис их увы отличается.

Автор: kosmonaFFFt 20.6.2012, 16:01
Ок, погуглю на эту тему...

Автор: Randajad 20.6.2012, 17:28
А почему нельзя написать внутренности библиотеки на C++, а экспорты сделать на C с возвратом кодов ошибок?

Автор: kosmonaFFFt 25.6.2012, 11:49
Тогда неудобно получается работать с функциями, которые должны что-то возвращать... Внутренности конечно можно на С++ написать, но опять же, даже исключениями нормально не воспользуешься...

Я пока склоняюсь к мысли протаскивать в каждую функцию последним аргументом указатель на структуру, в которую класть код ошибки и информацию о файле/строке, где ошибка произошла (и если хочется ошибку игнорировать, просто передавать NULL)...

Автор: Randajad 25.6.2012, 11:54
Да вроде как вполне удобно. Многие функции в винапе такие. По указателю передавать переменную, в которую будет писать результаты своей деятельности.
А насчет исключений можно по-подробнее? Мы же их кидать в приложение не будем.

Автор: kosmonaFFFt 25.6.2012, 11:58
Если делать библиотеку на C++ с интерфейсом на C и кидать исключения из начинки, то ничего хорошего не получится... Смысл тогда использовать C++ не вижу...

Автор: Randajad 25.6.2012, 12:07
Смысл - для удобства разработки библиотеки. smile
Али религия не позволяет писать на С++? smile
С слишком аскетичен.

Автор: kosmonaFFFt 25.6.2012, 12:48
Для моих целей вполне хватает и C, а все плюшки C++ типа ООП, исключений и шаблонов вместе с STL разбиваются об необходимость иметь интерфейс на C.

Автор: math64 25.6.2012, 12:52
Randajad, Ну вот допустим, библиотека написана на C++ с C-интерфейсом. Пользовательская программа - тоже на C++.
1. Библиотека и пользовательская программа компилируется одним и тем же компилятором - Ок, но зачем тогда C-интерфейс?
2. Библиотека и пользовательская программа компилируются разными компиляторами, для каждой нужна своя runtime-библиотека, могут быть проблемы.
Я как-то пытался состыковать программу, наприсанную на C++ Builder 6.0 с dll, написанной на C++ Builder 5.0 - проще оказалось перекомпилировать библиотеку на C++ Builder 6.0 чем заставить нормально работать вместе разные версии компилятора.

Автор: Randajad 25.6.2012, 12:53
Значит, религия.
Как ни крути, а количество кода, при написании на С резко увеличивается. Даже буста нету.
То, что экспортируемый интерфейс на С - не причина отказываться от многих возможностей языка. Тем более, 11 стандарт как никак.

Добавлено @ 12:54
Библиотека динамическая? Линкуем статически CRT.

Добавлено @ 12:56
С интерфейс нужен для каких-либо плагинов. Если же и библиотека и приложение разрабатываются одним автором, причем библиотека планирует использоваться только в этом приложении - зачем она тогда вообще нужна? Если же он ее позиционирует еще как отдельный продукт- это уже его дело, делать ей С интерфейс, или нет.

Добавлено @ 12:59
Вообще, я крайне не люблю тех, кто линкует CRT динамически. Особенно это касается студии. Из-за того, что люди не хотят, чтобы их экзешка распухла на 30 килобайт, юзверям приходится устанавливать метры всяких MSVC Redist...

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

Автор: kosmonaFFFt 25.6.2012, 18:38
Пользовательская программа будет с большой степенью вероятности на чем-то высокоуровневом, типа python+pyqt или .NET, соответственно C-интерфейс нужен для возможности создания биндингов в высокоуровневый язык...

Цитата(Randajad @  25.6.2012,  16:53 Найти цитируемый пост)
Вообще, я крайне не люблю тех, кто линкует CRT динамически. Особенно это касается студии. Из-за того, что люди не хотят, чтобы их экзешка распухла на 30 килобайт, юзверям приходится устанавливать метры всяких MSVC Redist...

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

Обычно нормальные авторы тогда делают нормальные инсталляторы, которые сами ставят редист...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)