Истории с тегом: программизмы

Всего историй: 896

1383

Счастливой отладки!

Однажды мне довелось «подхватывать» проект на C++, оставшийся от одного программиста, уволенного несправедливо (по его личному мнению). Впрочем, проект был почти завершён, и мне оставалось лишь немного дописать интерфейс, провести тестирование, отладку и сдать всё заказчику.

Как обычно, сроки поджимают, а я всё никак не могу разделаться с «ловлей блох»: приложение то работает нормально, то вдруг начинает глючить и вылетать на ровном месте. Как выяснилось, периодически возникало std::exception, но отследить, откуда оно бралось, у меня никак не получалось: казалось, что таинственная ошибка присутствует буквально всюду, при этом появляясь далеко не при каждом запуске.

Вечер пятницы. В понедельник начальство обещало спустить с меня шкуру, если что-то ещё не будет работать. Скидываю все исходники себе на флешку, хоть это и запрещено (к счастью, лишь на уровне инструкций), и несу домой в надежде разобраться, что к чему, за чашечкой кофе.

Дома первым делом в надежде на чудо запускаю экзешник — вылетает, сволочь. Ладно, запускаю полную компиляцию и иду чистить картошку. Возвращаюсь — ошибка!

В конце одного из основных хэдеров проекта, заботливо спрятанная за правый край экрана нужным количеством табуляторов, красуется неприметная строка:

#include


Гугление результата не даёт; просто комментирую эту строку и компилирую заново — успешно! Запускаю — программа работает как часы.

Придя в понедельник на работу, первым делом я решил глянуть, что же это за таинственная библиотека. Код её оказался настолько же лаконичным, насколько садистским:

#ifndef CFDC_H

#define CFDC_H

#include

#include

#define return if (std::random(1000) < 2) throw std::exception(); else return

//Счастливой отладки!

#endif



Надо ли говорить, что наш проект использовал в одном незначительном месте стандартный генератор случайных чисел, а вызываемый при инициализации std::randomize() успешно заметал любые следы?..

1381

Потоковый эксплойт

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

Маленький экскурс в компьютерную систему здания: все студенты работают на тонких клиентах, подключенных к могучему серверу с неадекватным поведением. Одной из черт его характера было то, что потоковый ввод надо закрывать дважды. Тёмные увлечения, а также нежелание сидеть на зачёте лишнее время не позволили пропустить такой шанс воспользоваться глобальной уязвимостью. Мной был написан код:

cin >> SumString;

cout << "Сумма строк: " << SumString;

На экране же это выглядело так:

> Это полов

> ина строки

> Сумма строк: Это половина строки

> Press any key to continue...

Пока препод в ведомости не расписался, нажимать на Any Key я не давал.

1378

А по вечерам хешируемся

Обожаю своё учебное заведение. Представьте такую картину: все сидят и увлеченно кодят. Заходит препод и видит, что две девушки оторвались от дебага и смотрят прямо перед собой застывшими взглядами. Каждая из них сцепила руки в кольцо, а позади стоит одногруппник и держит ладони на их головах.

— Что это с вами? — спрашивает препод.

— Связный взвешенный граф! Мы вершины, он — ребро, а это (взмах руками) — петли!

— Ага, я ребро весом 55, — соглашается одногруппник. Препод смеётся.

— А недавно мы были массивом и хотели покьюсортиться, но тренер нам не разрешил, — заявляет одна из вершин.

1319

Мёртвая говядина

Отлаживали как-то код (написанный не нами) на многопроцессной системе. «Плавающих» глюков было много, большинство проблем оказывалось в одном и том же процессе. Весь отдел курил листинги сутками, впрочем, мало результативно.

Какой-то добрый человек обратил внимание на дизассемблированный код процесса. В шестнадцатиричном виде проблемный сегмент записывался как «DEAD».

1305

Шестиразрядное сиденье

Часто «забавности» возникают на стыке IT-культуры и быта. В институте преподавали нам предмет «Вычислительные машины, системы и сети». Пары делились на лекции и лабораторные, вели их разные преподаватели, при этом планы занятий не были согласованы. В результате на лекциях читали одно, а на лабораторных требовали совершенно другое. На одной лабе заставили написать программу сложения двух чисел на эмуляторе микроассемблера. Имелся небольшой набор простейших микрокоманд, выполняемых процессором, и из них нужно собрать некую последовательность. При этом в программе необходимо было учитывать различные вариации исходных чисел — вроде бы задача несложная, но требует глубокого и осмысленного погружения в бинарное восьмиразрядное море.

Возвращаясь домой с одной такой пары, я, естественно, думал о прелестях двоичных чисел. Спускаюсь в метро, захожу в полупустой вагон, сажусь. Напротив меня ряд из шести сидений; на некоторых местах люди сидят, на некоторых — нет. В голове это осмыслилось как «100101». В вагон заходит еще один «бит» и уверенно встает слева от сидений, рядом с дверью.

Щ-щёлк! В голове моей что-то отчётливо хрустнуло: «Переполнение!»

1268

Суровая ASCII-правда

Недавно в институте мы начали изучать ассемблер. При отладке первой же программы со мной произошёл забавный случай. Так как ввод данных мы ещё не проходили, задание значений переменных и проверка результата производились через окно TASM'а, отображающее содержимое ячеек памяти и интерпретирующее эти данные как коды символов.

Так вот, после очередного запуска программы я лезу проверять результат, нахожу в памяти нужную переменную и обнаруживаю, что записано в ней не что-нибудь, а «xy☺». И правда — результат был действительно неверным.

1260

...а в военное время достигает четырёх

Решали задачу, суть которой сводилась к тому, чтобы дискретными отрезками достичь поверхности Земли, не выходя за пределы заранее заданного конуса. В качестве подзадач приходилось пересекать окружности, сравнивать углы между векторами и заниматься прочими трехмерно-геометрическими прелестями.

Всё готово, начинаем проверку. На одном тесте работает, на втором работает, на третьем — бац! — ошибка. В результате кропотливого дебаггинга обнаруживается проблемный кусок кода:

long double a1, a2;

a1 = PI / 2 + alp;

a2 = PI / 2 - alp;


После выполнения оказывается, что и a1, и a2 меньше, чем 1,57. Долго думали. Ещё думали. В итоге посмотрели в начало кода:

const int PI = 3.1415926535897932384626433832795;


Вот уж действительно: «Для простоты вычислений примем Пи равным трём»...

1241

d-_-b

Дело было на первом курсе университета — тогда мы только-только начинали осваивать программирование на Паскале. Я зашёл к одногруппнику, который в это время бился с непростой программкой аж на 100 строк кода. В процесс отладки тут же был втянут и я — просмотрел код, сделал пару-тройку исправлений... Программа работает, компилится, но результаты выдаёт явно не те. Полчаса мы перечитывали код, подправляли, оптимизировали; абсолютно правильная «на бумаге» программа ни в какую не хотела выдавать верный результат.

Никогда не забуду выражение лица товарища, обнаружившего причину мучений. Оказалось, что я, в первый раз правя код, вместо переменной b в одном из операторов влепил d. С тех пор я стараюсь называть переменные осмысленно, а однобуквенных имён и вовсе избегать.

1233

Мир 2.0: четырёхдневку за одни сутки

— Ты где такую Солнечную систему видел? Кто их так делает? Cоздай себе другой экземпляр системы и экспериментируй на нём.

— У тебя гравитационное поле есть?

— Есть, 36 на 36.

— Мне так много не надо.

— Сколько надо — столько и возьмёшь.

— Ты куда Юпитер дел? Что? Это Юпитер? Это дерьмо, а не Юпитер, совсем не похоже!

— У тебя с Марсом проблемы — скачет по небу.

— Куда ты дел звёзды и как их включать?

Шёл только первый день творения. До сдачи новой версии виртуального планетария оставалось целых шесть дней.

1209

Экстренное прерывание

В последнее время я сконцентрировался на программировании микроконтроллеров на Си и ассемблере. Столь глубокое погружение в новую тему не могло не сказаться на психике.

Итак, раннее утро, часов шесть. Должна приехать родственница жены; я сквозь сон слышу звонок в дверь. Супруга просыпается, идёт встречать гостью. В сонный мозг приходит мысль: «Прерывание от звонка в дверь сработало». Мысленно представляю себе текст программы, понимаю, что до следующего прерывания еще куча тактов, и спокойно ухожу в sleep mode c пониженным энергопотреблением.

Через какое-то время просыпается мелкий, и не обнаружив рядом мамы, начинает пинать меня ногами в живот. Возвращаюсь к листингу — это не прерывание по звонку будильника. Если это не прерывание, значит, меня пинает главный цикл. А как он меня может пинать, если я в sleep mode? Он обязан подождать следующего прерывания!..

С мыслью о найденном баге я окончательно просыпаюсь.