|
Программирование >> Перегруженные имена функций и идентификаторы
Впрочем, не будем распространяться долго об архитектуре libwww, желающие могут посмотреть документацию. Теперь нам хотелось бы пройтись по недостаткам. libwww со временем становится все сложнее и сложнее по причине увеличивающегося набора стандартных обработчиков. Зачастую, достаточно простая задача, но которая не предусмотрена изначально как типовая, может потребовать нескольких часов изучения документации в поисках того, какие обработчики и где должны для этого присутствовать. Документация на библиотеку не отличается подробностью и, как следствие, понятностью; она сводится к двум-трем строкам комментариев к программным вызовам, при этом местами документация просто устарела. Совет: если вы используете libwww, то обязательно смотрите исходный текст, по нему станет многое понятно. В качестве примера, можно привести такую вещь. Для того, чтобы отследить контекст разбора HTML, вводится специальный объект типа HText, который используется в обработчиках событий от парсера в качестве внешней памяти . Это как указатель this в C++, т.е. реализация объектов на языке Си. Тип HText целиком предоставляется пользователем, вместе с callback-функциями создания и удаления. Прежде чем его использовать, надо зарегистрировать эти функции (причем обязательно парой, т.е. надо обязательно указать и функцию создания объекта, и функцию разрушения), которые, если следовать документации, будут вызваны, соответственно, для создания и удаления объекта при начале и конце разбора соответственно. Это все пока что хорошо . Плохо - функция разрушения не вызывается никогда. В частности, в документации этого нет, но видно по исходному тексту, где в том месте, где должен был находится вызов удаляющей функции, находится комментарий, в котором написано, что забота об удалении ложится на плечи приложения, а не библиотеки libwww. Кто при этом мешает вызвать переданную функцию, не понятно. Кстати сказать, примеры использования объекта HText в поставляемых с libwww приложениях из каталога Examples, рассчитаны на то, что функция удаления будет вызвана. И это не единственное забавное место в библиотеке. Все это решаемо, конечно, но лучше если вы будете сразу же смотреть исходный текст libwww, по нему значительно больше можно понять, чем по предоставленной документации. Итак, использование libwww позволяет быстро написать типичное web-приложение, например, робота , который выкачивает определенные документы и каким-то образом их анализирует. Тем не менее, использовать libwww в своих программах не всегда просто из-за проблем с документацией на нее. Ошибки работы с памятью Когда программа становится внушительной по своему содержанию (то есть, не по количеству строчек, а по непонятности внутренних связей), то ее поведение становится похожим на поведение настоящего живого существа. Такое же непредсказуемое... впрочем, кое что все-таки предсказать можно: работать оно не будет. Во всяком случае, сразу. Программирование на Си и C++ дает возможность допускать такие ошибки, поиск которых озадачил бы самого Шерлока Холмса. Вообще говоря, чем загадочнее ведет себя программа, тем проще в ней допущена ошибка. А искать простые ошибки сложнее всего, как это ни странно; все потому, что сложная ошибка обычно приводит к каким-то принципиальным неточностям в работе программы, а ошибка простая либо превращает всю работу в бред пьяного программиста , либо всегда приводит к одному и тому же: segmentation fault. И зря говорят, что если ваша программа выдала фразу core dumped, то ошибку найти очень просто: это, мол, всего лишь обращение по неверному указателю, например, нулевому. Обращение-то, конечно же, есть, но вот почему в указателе появилось неверное значение? Откуда оно взялось? Зачастую на этот вопрос не так просто ответить. В Java исключены указатели именно потому, что работа с ними является основным источником ошибок программистов. При этом отсутствие инициализации является одним из самых простых и легко отлавливаемых вариантов ошибок. Самые трудные ошибки появляются, как правило, тогда, когда в программе постоянно идут процессы выделения и удаления памяти. То есть, в короткие промежутки времени появляются объекты и уничтожаются. В этом случае, если где-нибудь что-нибудь некорректно указать , то core dumped , вполне вероятно, появится не сразу, а лишь через некоторое время. Все дело в том, что ошибки с указателями проявляются обычно в двух случаях: работа с несуществующим указателем и выход за пределы массива (тоже в конечном итоге сводится к несуществующему указателю, но несколько чаще встречается). Загадки, возникающие при удалении незанятой памяти, одни из самых трудных. Выход за границы массива, пожалуй, еще сложнее. Представьте себе: вы выделили некоторый буфер и в него что-то записываете, какие-то промежуточные данные. Это критическое по времени место, поэтому тут быть не может никаких проверок и, ко всему прочему, вы уверены в том, что исходного размера буфера хватит на все, что в него будут писать. Не хотелось бы торопиться с подобными утверждениями: а почему, собственно, вы так в этом уверены? И вообще, а вы уверены в том, что правильно вычислили этот самый размер буфера? Ответы на эти вопросы должны у вас быть. Мало того, они должны находиться в комментариях рядом с вычислением размера буфера и его заполнением, чтобы потом не гадать, чем руководствовался автор, когда написал: char buf[100]; Что он хотел сказать? Откуда взялось число 100? Совершенно непонятно. Теперь о том, почему важно не ошибиться с размерами. Представьте себе, что вы вышли за пределы массива. Там может ничего не быть , т.е. этот адрес не принадлежит программе и тогда в нормальной операционной системе вы получите соответствующее матерное выражение. А если там что-то было? Самый простой случай - если там были просто данные. Например, какое-нибудь число. Тогда ошибка, по крайней мере, будет видна почти сразу... а если там находился другой указатель? Тогда у вас получается наведенная ошибка очень высокой сложности. Потому что вы будете очень долго искать то место, где вы забыли нужным образом проинициализировать этот указатель...
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |