Dale
|
|
« : 02-02-2011 09:15 » |
|
|
|
« Последнее редактирование: 27-07-2011 19:15 от RXL »
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Dale
|
|
« Ответ #1 : 02-02-2011 12:33 » |
|
Статья готова.
Обсуждаем, публикуем.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #2 : 02-02-2011 13:16 » |
|
Интересная статья. Не видел до этого ни одного логичного применения longjmp.
Добавлено через 1 день, 4 часа, 38 минут и 17 секунд: Интересно, каковы лимиты вложенности блоков таких try-catch?
|
|
« Последнее редактирование: 03-02-2011 18:12 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #3 : 03-02-2011 18:38 » |
|
Если я правильно понял, предложенное решение ловит только те исключительные ситуации, порождение которых прописано программистом. В случаях же ошибок типа деления на ноль данный механизм не сработает.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Dale
|
|
« Ответ #4 : 03-02-2011 19:25 » |
|
Интересно, каковы лимиты вложенности блоков таких try-catch? Документацией не лимитируется. Похоже, в разумных пределах вложенность не ограничена. Добавлено через 4 минуты и 36 секунд:Если я правильно понял, предложенное решение ловит только те исключительные ситуации, порождение которых прописано программистом. В случаях же ошибок типа деления на ноль данный механизм не сработает. Конечно. Штатного-то механизма обработки исключений в C нет, здесь приведена лишь его довольно искусная имитация при помощи longjmp и макросов. Поэтому перехватывать ошибки runtime при помощи CException не получится, равно как и ошибки подпрограмм стандартной библиотеки. Ну и, само собой, не удастся выбрасывать ничего более информативного, чем беззнаковое целое.
|
|
« Последнее редактирование: 03-02-2011 19:30 от Dale »
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #5 : 04-02-2011 07:28 » |
|
Если ориентироваться именно на микроконтроллеры, то не помню, чтобы там было деление (с системой команд AVR знаком давно, поверхностно и все уже забыл, а в 8051 и PIC деления нет как класса, в AD21xx исключения не полагалось, а с другими м/к не сталкивался). Исходя из этого предположу, что нужно внедрить в код функции деления соотв. Throw. При отсутствии защиты памяти (обычное дело в м/к и мобильных процессорах) других ошибок не будет. Не забываем, что ресурсов мало - тут не винда с дровами от неведомого индусского производителя. Т.е. код максимально контролируется разработчиком. Вывод: предложенный в статье механизм покрывает все потребности в обработке исключений.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Sla
|
|
« Ответ #6 : 04-02-2011 07:32 » |
|
а в 8051 и ... деления нет как класса,
ай-ай-ай Верни слова взад. Команда "div AB" выполняет деление содержимого аккумулятора на содержимое регистра "B". Частное помещается в А, остаток - в В
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Вад
|
|
« Ответ #7 : 04-02-2011 07:41 » |
|
Что-то с sourceforge? У меня не получается посмотреть исходники на сайте проекта - при попытке открыть ветку исходников страничка сваливается куда-то налево и ничего не кажет. Было любопытно посмотреть, как реализованы макросы. В статье на это, к сожалению особых намёков нет, а это ведь самое интересное Честно говоря, longjmp никогда не пользовался - как-то в голову не приходило даже, совмещать C и обработку исключений: в моём представлении, код на C должен быть или дубово надёжным, или не быть Правда, я на C по-крупному только видеокодек и обвязку к нему пилил, там ничего такого и не требовалось.
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #8 : 04-02-2011 07:44 » |
|
Каюсь, Слав. 13 лет прошло. Да и не использовал я эту команду. Сейчас вспомнил - 4 машинных цикла выполнялась.
Добавлено через 2 минуты и 22 секунды: Вад, прикрепил к посту.
|
|
« Последнее редактирование: 04-02-2011 07:47 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Dale
|
|
« Ответ #9 : 04-02-2011 08:02 » |
|
Не понял фразу: ...как-то в голову не приходило даже, совмещать C и обработку исключений: в моём представлении, код на C должен быть или дубово надёжным, или не быть Обработка исключений для того и введена, чтобы гарантированно реагировать на ошибочные ситуации. Наоборот, именно еe отсутствие очень затрудняет написание надежного кода на C (или же делает его чрезмерно громоздким, что и продемонстрировано в статье). Было любопытно посмотреть, как реализованы макросы. В статье на это, к сожалению особых намёков нет, а это ведь самое интересное Вад, прикрепил к посту. К статье приложен рабочий демо-проект, там включено все необходимое, включая исходники CException.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Вад
|
|
« Ответ #10 : 04-02-2011 10:19 » |
|
Не понял фразу: ...как-то в голову не приходило даже, совмещать C и обработку исключений: в моём представлении, код на C должен быть или дубово надёжным, или не быть Обработка исключений для того и введена, чтобы гарантированно реагировать на ошибочные ситуации. Наоборот, именно еe отсутствие очень затрудняет написание надежного кода на C (или же делает его чрезмерно громоздким, что и продемонстрировано в статье). Считаю последнюю фразу преувеличением В статье приведён не слишком удачный пример, когда проводится много проверок (к тому же, будто бы не к месту), которые к тому же непонятны -- в том смысле, что код элементарно плохо читается из-за всех этих проверок. Почему a <= fabs(b-c), а не c <= fabs(a - b)?
|
|
|
Записан
|
|
|
|
Dale
|
|
« Ответ #11 : 04-02-2011 11:29 » |
|
Почему a <= fabs(b-c), а не c <= fabs(a - b)? Не любые три отрезка могут образовать треугольник. Если взять два отрезка произвольной длины, то третий должен быть не больше их суммы и одновременно не меньше разности. Если угодно, можно взять условие c <= fabs(a - b), но тогда одновременно нужно проверить c >= a + b. Я просто не стал загромождать статью такими элементарными вещами, поскольку тема все-таки исключения в C, а не введение в геометрию.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Вад
|
|
« Ответ #12 : 04-02-2011 12:07 » |
|
Я просто не стал загромождать статью такими элементарными вещами, поскольку тема все-таки исключения в C, а не введение в геометрию.
Я это понимаю. В том и дело, что все проверки, без комментариев, выглядят не очень читаемо, скажем так. Не считываются как семантическая единица, что ли. Вот если вынести всё в предикат isValidTriangle -- то я бы сразу понял: вот, тут мы проверяем, правильные ли нам стороны подсунули, может ли это быть треугольником. Но когда есть такая проверка - вроде бы, нет нужды уже городить что-то насчёт проверки площади - просто возвращать -1 и задокументировать и в errno записать ошибку INVALID_ARG, раз нам такие плохие данные дают. А то и вовсе считать то, что дают, а предикат пусть клиент сам проверяет.
|
|
|
Записан
|
|
|
|
Dale
|
|
« Ответ #13 : 04-02-2011 12:40 » |
|
Так речь ведь о том и идет, чтобы забыть про -1 и errno. У нас ведь функция может участвовать в более сложном выражении, причем вызываться несколько раз. Можно, конечно, завести несколько временных переменных для сохранения результатов вызовов, проверять их значения на код ошибки, потом генерировать новый код и передавать вызывающей функции и т.д., но вариант с исключениями импонирует мне куда больше. Добавлено через 14 минут и 40 секунд:Вот простой пример. Наша функция вычисляет площадь треугольника. Она вызывается из другой функции, которая вычисляет объем призмы с треугольным основанием по известной высоте. В свою очередь, та вызывается из функции определения массы призмы по известной плотности вещества. Представьте себе красоту и изящество кода, который должен передать возможную ошибку при вычислении площади треугольника в главную программу через три уровня вложенности. А вот это: А то и вовсе считать то, что дают, а предикат пусть клиент сам проверяет. плохо вяжется с в моём представлении, код на C должен быть или дубово надёжным, или не быть Это скорее подход в стиле: "сами нарвались, так получите же по полной".
|
|
« Последнее редактирование: 04-02-2011 12:56 от Dale »
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Вад
|
|
« Ответ #14 : 04-02-2011 14:36 » |
|
Пример неудачный. Если есть корректная призма - для чего проверять корректность треугольного основания? А если нет - чего ради нам считать площадь этого основания, если призма уже некорректная? Это скорее подход в стиле: "сами нарвались, так получите же по полной".
Это подход "что дали, с тем и посчитали" - нормальный подход, в такой задаче ничем не хуже прочих. С тем же успехом подход с CException можно назвать "сами нарвались на исключение - сами и ловите". Это лишь вопрос контракта: кто должен отвечать за корректные значения, подпрограмма или клиент. И каким образом клиент будет справляться с некорректным поведением. Если вы видели java-код с развесистым набором catch-ей, то не понимаю, как можно находить этот подход "лучше" и "красивее", чем обработка errno и возвращаемых значений. Исключения нужно очень рано перехватывать, иначе что число вариантов исключений, что число возможных некорректных поведений программы, будет расти, и неважно, чего будет много: веток с проверкой, какой код ошибки в errno, или веток catch, проверяющих, какое, всё-таки, исключение из возможных 5 было сгенерировано. В общем, механизм исключений - это не вопрос уменьшения объёма кода и повышения его наглядности, в любом случае. Это лишь другой механизм делегирования ошибок, который, разве что, чуть более сложно игнорировать. А игнорирование ошибок - это скорее вопрос дисциплины программиста и покрытия кода тестами. То есть, вопрос комплексный, касающийся организации процесса разработки в целом.
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #15 : 04-02-2011 16:27 » |
|
Это, конечно, вопрос вкуса. Но лично мне нравится раздельно описывать основной и альтернативные сценарии какой-то деятельности. Единственно, что при помощи данного механизма, который требует написания if и вызова throw, делать такое разделение не очень удобно. Если только каждую проблемную функцию оборачивать в другую функцию, которая делает нужные проверки и генерирует соответствующие исключения. Однако, количества кода это не сокращает.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Вад
|
|
« Ответ #16 : 04-02-2011 17:55 » |
|
Ещё один минус - работа с памятью. Поскольку C - язык не так чтоб совсем объектный, подчищать динамически выделенные ресурсы после throw будет просто некому, и в таких случаях будут течи. Или будет неаппетитная очистка всех ресурсов перед каждым throw, что несколько испортит раздельные сценарии для Димки.
Теоретически, сюда можно прикрутить какой-нибудь Symbian-подобный механизм со специальным порядком инициализации на куче, но это тоже будет костыль.
|
|
« Последнее редактирование: 04-02-2011 17:59 от Вад »
|
Записан
|
|
|
|
Sla
|
|
« Ответ #17 : 04-02-2011 18:46 » |
|
Вад, этот вопрос я тоже хотел задать, но у меня БОЛЬШАЯ проблема со знанием С. поэтому библиотеку посмотрел вскольз. например в Паскале есть такой оператор mark (если память не изменяет), который запоминает состояние кучи на момент вызова.) а затем можно вернуть все назад, вызвав соответствующий антиоператор, который все это освободит. И мне показалось, что это реализовано в библиотеке CException. Но при работе с микроконтроллерами работа с кучей это ВРЕДНО - памяти там для этого нет. Я не говорю о монстрах с 64к на борту, а всего лишь 16К, ну или около того. Offtopic: А потом удивляемся - почему такие мелкие вещи используют такие мощные контроллеры
Поставлю в угол.
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Dale
|
|
« Ответ #18 : 04-02-2011 19:31 » |
|
Пример неудачный. Если есть корректная призма - для чего проверять корректность треугольного основания? Если бы данные всегда были гарантированно корректными, вопрос дефектов ПО вообще утратил бы актуальность. Но мы все еще живем в реальном мире. Где их брать, эти идеальные призмы? А если нет - чего ради нам считать площадь этого основания, если призма уже некорректная? У нас в програмном мире нет никаких призм. Есть набор параметров, полученных от клиента, и у нас нет оснований слепо им доверять. Нам нужно написать код, который ведет себя предсказуемо в любых условиях. Не забываем, что речь идет о встроенном софте, а не о студенческой лабораторной. Это скорее подход в стиле: "сами нарвались, так получите же по полной".
Это подход "что дали, с тем и посчитали" - нормальный подход, в такой задаче ничем не хуже прочих. С тем же успехом подход с CException можно назвать "сами нарвались на исключение - сами и ловите". Это лишь вопрос контракта: кто должен отвечать за корректные значения, подпрограмма или клиент. И каким образом клиент будет справляться с некорректным поведением. Не совсем так. При опросе нерадивый клиент может не проверить код ошибки и продолжить выполнение с некорректным результатом. Исключение принудительно прервет поток выполнения. Если вы видели java-код с развесистым набором catch-ей, то не понимаю, как можно находить этот подход "лучше" и "красивее", чем обработка errno и возвращаемых значений. Скажем так, я не фанат Java, мне ближе C#, но в данном случае это большой роли не играет, наверное. Исключения нужно очень рано перехватывать Кому нужно и зачем? Я предпочитаю перехватывать их в том месте, где их можно осмысленно обработать, а не просто передать код завершения дальше по цепочке вызовов в надежде, что им кто-то заинтересуется. И это совсем не обязательно "очень рано". иначе что число вариантов исключений, что число возможных некорректных поведений программы, будет расти, и неважно, чего будет много: веток с проверкой, какой код ошибки в errno, или веток catch, проверяющих, какое, всё-таки, исключение из возможных 5 было сгенерировано. Опять же совсем не факт. В отличие от CException, в Java и C# исключение - это объект, производный от базового класса исключений, и если построить дерево подклассов исключений с умом, можно единообразно обрабатывать целые семейства исключений, а не охотиться за каждым по отдельности. В общем, механизм исключений - это не вопрос уменьшения объёма кода и повышения его наглядности, в любом случае. Это лишь другой механизм делегирования ошибок, который, разве что, чуть более сложно игнорировать. А игнорирование ошибок - это скорее вопрос дисциплины программиста и покрытия кода тестами. То есть, вопрос комплексный, касающийся организации процесса разработки в целом. Примерно то же можно при желании сказать об объектно-ориентированном программировании по отношению к структурному. А также о структурном программировании по отношению к GOTO, пожалуй. Можно писать отвратительные объектные программы и отвратительные структурные. Сам по себе инструмент совершенно ничего не значит, если его использование не следует определенной дисциплине. Механизм исключений позволяет решить на самом деле очень важную задачу - произвести обработку ошибки в той точке программы, где это наиболее уместно, а не в той, где она возникла. Если его использовать как-то иначе, например, пытаясь перехватить исключение "очень рано", толку от них действительно будет немного. Тут я полностью согласен. Мне кажется, что можно провести такую параллель с миром оборудования: исключение - это прерывание, а проверка кода ошибки - это опрос (поллинг). Какая система ведет себя логичнее: та, которая реагирует на события по прерываниям, или та, которая постоянно проверяет, не случилось ли чего?
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Sla
|
|
« Ответ #19 : 04-02-2011 19:36 » |
|
Мне кажется, что можно провести такую параллель с миром оборудования: исключение - это прерывание, а проверка кода ошибки - это опрос (поллинг). Какая система ведет себя логичнее: та, которая реагирует на события по прерываниям, или та, которая постоянно проверяет, не случилось ли чего?
Сбалансированная. С точки зрения работы приложения(девайса)
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Вад
|
|
« Ответ #20 : 04-02-2011 19:37 » |
|
например в Паскале есть такой оператор mark (если память не изменяет), который запоминает состояние кучи на момент вызова.) а затем можно вернуть все назад, вызвав соответствующий антиоператор, который все это освободит. И мне показалось, что это реализовано в библиотеке CException.
Не знаю точно, как реализована куча в Паскале, но явно на более высоком уровне, чем в С. Насколько я понимаю документацию на setjmp/longjmp, ничего такого оно не умеет, сохраняя лишь позицию указателя на стек, точку в коде и ещё некоторые регистры. Закрывать дескрипторы и освобождать память это не поможет. Но при работе с микроконтроллерами работа с кучей это ВРЕДНО - памяти там для этого нет. Я не говорю о монстрах с 64к на борту, а всего лишь 16К, ну или около того.
Нет, ну для микроконтролеров я ничего и не говорю. Там, может, и не надо. Хотя, тут можно и про те же дескрипторы вспомнить или взять другие случаи, когда надо будет сброс состояния какого-то делать...
|
|
|
Записан
|
|
|
|
Dale
|
|
« Ответ #21 : 04-02-2011 19:50 » |
|
например в Паскале есть такой оператор mark (если память не изменяет), который запоминает состояние кучи на момент вызова.) а затем можно вернуть все назад, вызвав соответствующий антиоператор, который все это освободит. И мне показалось, что это реализовано в библиотеке CException. Да, был такой в младших версиях Pascal. Там куча распределялась практически как стек, только навстречу ему - снизу вверх. Оператор mark попросту запоминал текущую верхушку кучи, а парный к нему release восстанавливал ее обратно, уничтожая все, что накопилось в куче между вызовами mark и release. Для упрощенных компиляторов это было проще, чем следить за кучей. В CException ничего подобного нет, куча здесь не задействована. Используется другой механизм setjmp/longjmp, который относится к потоку управления, а не к данным. Но при работе с микроконтроллерами работа с кучей это ВРЕДНО - памяти там для этого нет. Совершенно верно. С кучей в случае firmware шутки особенно плохи - ресурсов мало, поэтому гораздо лучше жестко распределить их заранее статически и не баловаться в динамике. В крайнем случае выделять в ней дополнительные буферы, без которых в принципе можно бы и обойтись. Я не говорю о монстрах с 64к на борту, а всего лишь 16К, ну или около того. Это еще смотря какое семейство МК. У AVR, например, 16К - это как раз монстры, старшие модели. А у середнячков и килобайт не всегда наскребется. И у PIC вроде бы не лучше с этим. Добавлено через 7 минут:Ещё один минус - работа с памятью. Поскольку C - язык не так чтоб совсем объектный, подчищать динамически выделенные ресурсы после throw будет просто некому, и в таких случаях будут течи. Или будет неаппетитная очистка всех ресурсов перед каждым throw, что несколько испортит раздельные сценарии для Димки. Можно следовать такому паттерну: - Создаем динамический объект.
- Работаем с ним в защищенном блоке (Try).
- Обрабатываем возможные ошибки (Catch).
- Освобождаем динамический объект.
Вроде бы нет лазеек для утечки. Кто создает, тот и обязуется за собой подчистить кучу. Ну и см. мой предыдущий ответ Sla: кучей не злоупотребляем без крайней на то необходимости.
|
|
« Последнее редактирование: 04-02-2011 19:57 от Dale »
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Вад
|
|
« Ответ #22 : 04-02-2011 19:59 » |
|
У нас в програмном мире нет никаких призм. Есть набор параметров, полученных от клиента, и у нас нет оснований слепо им доверять. Нам нужно написать код, который ведет себя предсказуемо в любых условиях. Не забываем, что речь идет о встроенном софте, а не о студенческой лабораторной.
Я лишь поставил под сомнение, на каком уровне модели должна выполняться проверка входных данных. Речь ведь идёт не о read-only коде. При опросе нерадивый клиент может не проверить код ошибки и продолжить выполнение с некорректным результатом. Исключение принудительно прервет поток выполнения.
и куда уйдёт longjmp, если забыли сделать setjmp, а ошибка произошла, но не была протестирована? Что помешает устройству сломаться уже в руках покупателя? Механизм исключений позволяет решить на самом деле очень важную задачу - произвести обработку ошибки в той точке программы, где это наиболее уместно, а не в той, где она возникла. Если его использовать как-то иначе, например, пытаясь перехватить исключение "очень рано", толку от них действительно будет немного. Тут я полностью согласен.
Я полностью согласен. И механизм errno тоже позволяет это делать. И баланс между этими двумя соблюдать всё равно придётся, иначе будет Java/C#-быдлокод с кучей catch-ей на верхнем уровне, а при неумении препроцессора следить за "утекающими" из функций исключениями -- ещё и морока по поддержанию актуальной документации на все функции, способные эти исключения генерировать. Механизм исключений - штука удобная для очень своих целей: когда ошибка может произойти на уровне, некомпетентном для её обработки. Но эта ошибка должна быть поистине фатальной и сложно- или непредсказуемой до погружения на оный уровень (исходя из внутреннего состояния программы). Ошибка ввода может и фатальна, но проста, предсказуема и вполне себе тестируема. Как и деление на ноль, например. Поэтому я не согласен с примером, а не потому, что мне вся идея целиком не нравится. Идея - отличная. Но я не согласен с тем, что она позволяет писать более простой и надёжный код. Граблей здесь примерно столько же, а код проще не становится. Просто это другой способ мышления об ошибках, как вы абсолютно верно и заметили: вместо постоянной паранойи "тут может быть ошибка? проверяем, в случае чего - делаем return" получается схема "эта функция нам генерирует исключения? ага, пусть идут выше, а вот тут мы их перехватим и обработаем". Вместо "рефлекторных" (ну, не совсем, но что-то в этом есть) проверок всего и вся - вдумчивая работа с документацией на функции (в противном случае всё пойдёт прахом). Внимания такая техника требует, на мой взгляд, не меньше. На моей практике, багов с обработкой исключений в командных проектах было не меньше, чем с игнорированием или путаницей в кодах возврата. И баги были подчас куда более серьёзные.
|
|
« Последнее редактирование: 04-02-2011 20:05 от Вад »
|
Записан
|
|
|
|
Sla
|
|
« Ответ #23 : 04-02-2011 20:04 » |
|
ага..., давно в руки шашечек не брал (даташитов не читал), виноват - про память указанную мной на борту МК эту супермонстр.
А вот исключения... это как раз и есть безопасный способ проверки входных данных.
Эта статься не рекомендация использования исключений, эта статья показывает как можно использовать исключения.
Честно... не люблю систему исключений... Она затрудняет (мне) чтение и понимание кода Мне гораздо понятней в работе МК линейный код. Но такие конструкции типа longjump использовать приходилось при вызове критических функций обработки данных.
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Вад
|
|
« Ответ #24 : 04-02-2011 20:09 » |
|
Честно... не люблю систему исключений... Она затрудняет (мне) чтение и понимание кода Мне гораздо понятней в работе МК линейный код.
Вот я тоже сегодня, когда пытался Димке объяснить суть моих претензий к идее "исключения на C", прежде всего пытался выразить, что я чувствую, когда подумаю, что строго императивный код вдруг посредине набора инструкций могут прервать и выдернуть на три уровня вверх в точку обработки. Интуитивную тревогу, вот что Про саму идею - опять же, я не говорю, что это зло, но проще от этого жизнь не становится, она становится только разнообразнее Но это и неплохо. Чем богаче средства - тем точнее можно описывать идеи в коде. Offtopic: ЗЫ. В "Мотороле" мне расказывали легенду про чувака, у которого на C-шных макросах была построена система шаблонов (templates) а-ля C++, не говоря уже про ООП. Так что есть ещё горизонты Поставлю в угол.
|
|
« Последнее редактирование: 04-02-2011 20:13 от Вад »
|
Записан
|
|
|
|
Dale
|
|
« Ответ #25 : 04-02-2011 20:23 » |
|
Ошибка ввода может и фатальна, но проста, предсказуема и вполне себе тестируема. Как и деление на ноль, например. Поэтому я не согласен с примером, а не потому, что мне вся идея целиком не нравится. Тут есть тонкость. Клиент может попросту не знать о существовании ошибки и о методе ее детектирования. Например, система получает данные непосредственно с датчиков, которые могут сбоить. Надежный компонент, который сам умеет проверить корректность данных и сообщить об ошибке, ценнее с точки зрения возможности повторного использования. Идея - отличная. Но я не согласен с тем, что она позволяет писать более простой и надёжный код. Насчет простоты спорить не стану, тут скорее вопрос привычки. А вот насчет надежности - при любой ошибке выполнение программы прерывается и уходит на Catch. Как минимум у нас есть гарантия, что основная ветка программы не будет выполняться с некорректными данными. Конечно, можно накосячить и в разделе Catch. Но никакой макрос не сможет заменить мозг программиста, тут ничего не поделаешь. Добавлено через 4 минуты и 54 секунды:Честно... не люблю систему исключений... Она затрудняет (мне) чтение и понимание кода Мне гораздо понятней в работе МК линейный код. Не сложнее аппаратных прерываний, IMHO.Тут хотя бы точно знаешь точки, в которых может возникнуть исключение. А прерывания все равно от линейности кода не оставляют камня на камне. Добавлено через 17 минут и 13 секунд:Offtopic: ЗЫ. В "Мотороле" мне расказывали легенду про чувака, у которого на C-шных макросах была построена система шаблонов (templates) а-ля C++, не говоря уже про ООП. Так что есть ещё горизонты Поставлю в угол. Хоть у нас тут и не Motorola, но дальнейшее предполагаемое развитие темы - как раз ООП на C. Потому что firmware подразумевает качественный софт, а качество без тестирования как-то трудно себе представить. Ну а дальше все по накатанной - какое же тестирование без всяких моков/фейков/стабов и т.д. Да и нормальный рефакторинг без объектной модели тоже немыслим. Так что это не оффтоп, а вполне реальная перспектива.
|
|
« Последнее редактирование: 04-02-2011 20:45 от Dale »
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Sla
|
|
« Ответ #26 : 04-02-2011 20:48 » |
|
Dale, при написании кода, я не знаю о прерываниях ничего, за исключением критических моментов, это мы проходили в предыдущей статье. И я даже могу и не знать о существовании таковых. Прерывания они как демоны, все знают что есть, но никто не видел.
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Dale
|
|
« Ответ #27 : 04-02-2011 20:54 » |
|
А как же без прерываний? На опросе? В этих поллингах недолго и увязнуть с головой...
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Sla
|
|
« Ответ #28 : 04-02-2011 21:02 » |
|
Ты не понял. Прерывания существуют. Но при описании основного цикла работы контроллера я о них ничего не знаю, за исключением того что данные забираю, вон с той полочки, и при этом я должен эту полочку закрыть амбразурой, чтоб никто-никто туда в этот момент не влез. Больше я о прерываниях ничего не знаю. И знать не хочу. Задача прерываний - принять данные, в случае критических секций принять решение о прекращении основного цикла, уйти на обработку "аварии" или, но никоим образом не вмешиваться в код выполнения основного цикла.
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Dale
|
|
« Ответ #29 : 04-02-2011 21:18 » |
|
Аналогично исключения позволяют абстрагироваться от ошибок при написании основной программы. Если где-то что-то случилось - это обрабатывается в другом месте и к решаемой задаче непосредственного каательства не имеет.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
|