Искусство программирования на Си (984073), страница 25
Текст из файла (страница 25)
Шредингер придумал этот умоз- ° Исходный код вместе с заголовочными файлами приводит к перемещению данных в памяти, н в рсзуль- ние только на Катином компьютере. рительный эксперимент для демонстрации того, что он ° Вся доступная документация тате этого р начинает указывать на совершенно безобнл- Наиболее раздражающей является ошибка Мандель- считаз неотъемлемо присущим квантовой теории. нос место. брота, при которой прекращается даже выполнение Ошибка Шредингера — это так называемая ошибка, ° Тестовыс сценарии, Условия, ланныс Что жс мы можем с этим сделатьо Первая линия программы Это особенно расстраивает, когда вы знае- находящаяся в состоянии спячки. Программа служит в ° Ожидаемыс результаты тестов обороны строится путем инициализации всех указатс- те, что ваша программа прекрасно работает на другой течение многих лет.
Затем кто-то находит ошибку, чи- Перегара<ретив<а е С Часть! И<яра<ааааа кода яра<рака ффйй)<ф 4 Глава У Листинг 2.8. Считаем ошибки. массива, на который указывает 5. Зто приведет к неопределенному поведению. Семь ошибок. В вызове функции рплю, начинающемся на 23-й строке текста, аргументы Ь и с излишни. Я нс собираюсь считать это ошибкой, но это может помешать вы- рг1ясг( Всгбяч< Ъя (бд евггуея).ув "СЬавчя иибсЬ сЬагасеег Ео '1'7 ягг1ея(в))< ясаст("тд", ба); Резюме В этой главе было рассмотрено несколько полезных 20 я)а)= '1'7 с<я(г)еп(я). Ошибочная проверка увеличивает счет оши 21 бок до девяти 1 41пс1яде <ясд1о.Ь> 2 41сс1сде <ааяегГ.Ь> 3 4 Ядетупя ВИАР(х, у) х"= у"= х; 5 б < се 7 па).я() в ( 9 сЬаг ея="стихух < 10 сЬаг 11 ясягсяед 1ояч а, Ь, с; 12 гас 13 14 15 1б 17 10 19 аяяеге((0 <= а) 44 (а < яег1еп(я))) возрастающий от значения Ь, и второй, убывающий от значения с, и использовать проверку Ь<с.
Двенадцать ошибок. И наконец, пространство, выделяемое функцией шайс<, вообще нс используется в программе. Вы должны согласиться с тем, что это не является ошибкой, поскольку память лолжна быть очищена для нас в любом случае, т.е., строго говоря, это не ошибка. Итого я нас <итая двенадцать ошибок.
Вы, может быть, насчитаете еще больше, если будете строже, чем я. Сколько я всего пропустил? Зта программа — яркий пример плохого стиля. Вы мо<ксте включить нечто подобное в процесс собеседоя ванна, проводимый вами с претендентами на работу по программированию или отладке программ. зову. В 26-й строке переменные а и Ь передаются в функцию асана, но проверка последующей части кола показывает, что подразумевались Ь и с. Зто логическая ошибка. Таким образом, имеем воселп ошибок.
Будем предполагать для дальнейшего анализа, что мы исправили эту строку. Нс проверяется также значение, возвращаемое ясапГ, но я не собираюсь еще раз засчитывать эту ошибку. При виде оператора контроля в строке 27 я был крайне удивлен. Конечно, лолжна быть проверкаЬ<=0. Если уж мы проверяем это, мы должны также проверить Ричард Хэзфалд У тели — это не массивы, а массивы — это не указатели. Итак, какил~ же образом следует выделять память правление памятью )ак получилось, что онн являются синтаксически эк- для строки? Никс привелены два возможных способа: впвалснтными формазьными параметрами при объявле- спег е [ЗЗ); нии функции, исключительно из-за того, что компилятор сводит прслставлснис массива к прелставлснию вессру(в, -ветхо мосха.
-); указатсля, а это может привести к некоторои путанице. 'е.райне важно уделять лостаточнос эппл~ание томл, как ваша программа и стандартная библиотека исполь- сьвх *вн В ЭТОИ ГЛАВЕ зуют память. Например. функция типа ыгсру, будучи Р = маыос()З) )й(р )= ввьь) описанной как получающая сйаг * в качестве первого ( ° Управление памятью ар» мента, в действительности должна принимать адрес всгсру(р, "Не)(о ыог1г). ); первого элемента массива сйаг, лосгаточно болывого лля ° Обшие ошибки использования памяти сохранения копии исходной строки, опрелеленной во вто- l* здесь осуиествияйте необходимые ° Сбои функции выделения памяти роч аргументе Просто персчать неинициализированную ооерааии со серо"ой '1 ° Успешное выполнение функции са!)ос переменную сйаг* (или, как я однажды увидел в Ч'сб- сети, алрос одного символа!) не слишком хорошо.
° Занимаемся контролем А вот другой пример неправильного использования Следует заметить, что для испольювания функции а(гсру необходимо написать И(пс[ийе <х(ппд.й>, а для Эта глава посвящена нс только реализации функций ся и другис, а мы часто не в состоянии оцени~ь важ- (слс~ка отредактированный. чтобы скрыть личность гесвгв р Ш3- Пера ыип~ренныи яяын С Уириа ение паияепыи й1®ДЯ 1 ° — ЯЩ 1 Часть! Глава В которой она не должна прикасаться, что приводит к В качестве другого примера того, что я имею в виду, Листинг 8Л.
Недопустимое использование неопределенным результатам. рассмотрим двусвязный список: В системах со стсковои организацией (другими сло- ) Сурепее вегасе ДееЬ1е11ее сваг *АеаптехСР11е(Р1ЬБ Тр) вами, в большинстве систем) довольно легко задать функции йе(я() такук1 входную строку., при которой есгесс левые1(хс *вехе; вгхе с аухе = в ° Эта функция возврашаст указатель на максимально будет уляышлснно псрсзаписан адрес возврата в стеке и вегасе девЫе11ве 'ргет; возможную копию в памяти входного файла (или полставлсн алрес враждебной агрессивной програмлеы. вегасе РОО рау1оал; сваг *р = НВЬЬ; МЗЕ(., если самый первый заказ памяти не лдазся).
В Что леожет сделать такая агрессивная програляма? В дсйцоеЫе11вее случае неполного прочтения она присваивает перемен- ствительности все, что захочет кракер. А это уже пря- дая создания этого списка вы начнете с довме((ьз*, сьаг Ьв(тег(126 П ной, содсржашсй информацию об ошибкам, ненулевое мая угроза безопасности вашей системы. Никогда не которому присвоите результат вызова шайос. Результа- значение. Здесь нет утечки памяти (хотя, конечно. вы- используйте йе(ао! (Почти такая жс строка арпмснтов ты послсдуюших вызовов швйос для дальнейших свя- ( зываклцая функция ответственна за освобожленис па- применилеа лля зсапто при чтении строки данных, раз- зеи в списке будут присвоены различным экземплярам 1ев вег1ев(ьвт(ег) мяти в соответствуюшес время). ница между этими двумя функциями заключается в >казателеи пех( и ргет.
Поскольку можно использовать том, что функцию всапГ() при осторожном обрашснии эти указатели для псремешения к любому элементу в вегсру(р + влге, Ьвтуег)1 Использование памяти, которая не агхе += 1ев; люжно использовать корректно.) Возьмитс ссбс за пра- списке, го, пока у вас есть указатель на любое мссто в > выделена вило использовать вместо йе1х() функцию гйе(з(). списке, нет никакои необходимости сохранять исхол- геевгв р; Я не знаю ночсму, но многие програмлшсты лумают, ный указатель. Ошибки при сохранении адреса При вызове функции распределения памяти нсобходиОтсутствие проверки возвращаемых г г - — Вг — яав — жее случиться, что выделенной области памяти нсдоыв11е (р ! = НОЬт ) Пересннлреннеий н>нн С Щ~~ Часть ! В некоторых странах влалслсц, застав вас в ломе.
может таковой к моменту завершения программы. В конце Сбои функции выделения памяти несколько обших заключений в точном соответствии с даже пристрелить вас на месте (несколько экстрсл>вль- концов, программа может быть написана на С, но ведь природой наших требований к памяти. ный вариант неопределенного поведения). Налзного нез ннкакил требований относительно того, что вызы- Это обычный код для обработки ошибок: безопаснее удостовериться, что вы сохранили все вал> ваюшая программа должна быть написана на С, не так Проанализируйте требования памяти Р = аа11ос(ьусав) з необходимое, перед пс сдачей п ава собственности.
р р р с пенности. зи. То, что произойдет сразу после завершения про- >и' т 1((р == ВОЬЬ) Действительно ли трсбуюгцаяся нам память должна Это только иллюстрация, и, как сказач Бьерн Стра- граммы, написанной на С, выхолит за пределы стандар- ( быть одним цельным блоком'? Если ответ отрицательуструп (В)агпе В>гоцлггир), "доказательство путем анато- та С.
Сушсствуст распространенное мн ос мнение, что операрг1яг(("Сао'Е а1)асаее еоооЧЬ аеаогу. ° . ный, то, возможно, мы сможем выполнить два запроса. гии является обманом". Если это не о уд влстворило вас, ционная система освог>одит память, когорая была ах)в(вхгт ватьпдв) > Когда вы вызываете шалос(), он старается найти один обратитесь к раздел 7.20.3 станда та С, в кото ом г - и р р . у... р, оро го- использована програлзмой. когда эта программа завер- блок свободной памяти, достаточно большой, чтобы ворится: "значение указателя, кото ый казыва р й указывает на шит свою работу. Для многих операционных систем это уловлетворить ваше требование. Если он может найти освобожденнук> область, нсопрсдслено".
Другими ело- верно; в действит льн е"ствитсльности это почти верно для операДзя "студенческого" кода это совсем неплохо. Про- . д п и й и б „- достаточно большой блок, он возврашает указатель на вами, обрашение к освобожленной области памяти прн- ционных систем наиболс обш г и и олсс о шсго использования. о . Н верка необходима, поскольку может произойти сбой в кт но на„иоанном него. Если не может, то возврашает Н(ЛЛ..
ЗапРашиваЯ водит в результате к неопределенному поведению. Го же стандарт С нс ласт никаких га т> й т ран з ого, что это так. функции шалос. На практике в корректно написанном два меньших блока, вы облегчаете шайос() жизнь, и самое можно сформулировать иначе: вы не можетс га- Хорошей программист ей про аммистско > практико валяется при' й студенческом коде о зень редко происходит сбои при действительно может оказаться, что он справится с двурантировазь определенность повеления своей програм- вычка убирать за собои, ес и ать за со ои, если можно так выразиться.
т.е. выделении достаточного объема памяти, поскольку тре- ям бай- мя ваши и рсбования и. мы, и теоретически она может заставить компьютер оставлять после себя ко. пь после сс я компьютер в том жс состоянии, в бусмос количество стремится к нескольким сотням байпроизводизь любое дсиствис, доступное см» физичес- каком он бьш ло пашен работы с ннм. Возврашсние тов и при каждом конкретном запуске прогР™м~ з~- ИГПОЛьауйтЕ МЕНБШЕ ПВМятИ ки, включая и различные возможности отправления динамически заказанной памяти вл ки заказанной памяти является частью этого прашнвается всего несколько таких блоков (разве что сообщений по электронной почте вашсму начальнику, про . Е б процесса.