Учусь на вечернем, а днём работаю. После работы и учёбы прихожу домой, а там двое маленьких деток, муж и кошка. Уроки делаю по ночам — короче, последние пару лет я нахожусь в перманентном состоянии недосыпа.
В университете задали написать лабу: вводишь дату, а программа рассчитывает и выводит, на какой день недели эта дата выпадала, с учетом юлианского, григорианского календарей и прочих исторических поправок.
Пишу, компилирую, всё в порядке, но результата нет. Это ясно — хоть когда-нибудь программа начинала работать с первого раза?.. Значит, где-то я накосячила. Лезу разбираться в код — всё ОК. Отлаживаю «step by step» — программа считает, но результата по прежнему нет!
Я вылизала каждую строчку в коде. Я переписала основной алгоритм трижды. Все логично построено, безошибочно компилируется, а результата нет! В последную перед сдачей ночь я просто начала плакать. Только утром перед зачётом я нашла проблему. Среди заумных алгоритмов отсутствовала лишь одна строчка кода:
Фиксили как-то баг в одной программе. Делали ее какие-то индусы для забугорного заказчика, а нам досталась поддержка.
Структура программы была такова: имелось несколько форм, каждая с меню. По выбору пункта меню пользователь переходил на новую форму или возвращался на предыдущую. Прототип формы имел четыре основных метода: конструктор/деструктор и колбеки входа/выхода. Когда пользователь уходил «вглубь», формы не удалялись, а складывались в линейный стек, поскольку по задумке юзеру всё равно придётся через них возвращаться. Удаление форм и их ресурсов происходило при возврате назад по удалению из стека.
Баг заключался в том, что на одной из форм, если ее пройти несколько раз, меню увеличивалось, наполняясь дублирующимися пунктами. Оказалось, наполнение этого меню происходило не единожды, в конструкторе (как и везде по проекту), а каждый раз при заходе в форму. Я перенёс несколько строк — заработало на ура.
Решил позвать старшего по отделу, сурового программера, чтобы он тоже подивился индийской мудрости. Он полистал код, позадавал много общих вопросов и молвил:
— Возвращаем как было, а по событию выхода просто очищаем меню. — Да тут во всём проекте именно так! Меню по-любому очистится, когда форма из стека уйдет. — Не знаю, как разработчики этой программы, но лично я подтираюсь после того, как сходил в туалет, а не перед тем, как сходить куда-либо ещё.
Это окончательно развеяло сомнения о вариантах фикса и означало многодневную переделку всех форм по проекту. В итоге заказчик сказал отдельное спасибо нашей команде за проделанную оптимизацию.
Я — программист. Пишу на «плюсах», фортране и питоне. Веб-программирование недолюбливаю, а флэш терпеть не мог никогда.
Как-то раз позвонила (!) мне приятельница, отличный веб-дизайнер из Москвы. Есть, говорит, проект, платят много. Срок — двое суток, Платформа — флэш. Подумал я и придавил своё самолюбие — раз столько платят, можно и взяться.
Вот только есть проблема — я никогда ничего не делал на флеше, технологию представлял себе весьма условно, и, что хуже всего, у меня стоял линукс, а среды флэш-разработки под пингвинячью ось тогда не было (может, сейчас уже появилась?) С другой стороны, наша дизайнерша — настоящая дизайнерша, со вкусом и чутьем, но её познания в программировании ограничены одним семестром паскаля, да и то давно.
Так и сидели мы 36 часов подряд за компьютерами: я в Самаре, подругав Москве. Связь держали через джаббер. У меня открыты текстовый редактор и руководство по ActionScript в PDF; у неё — родная среда разработки (тогда еще, кажется, от Macromedia). Я вслепую писал код, опираясь только на описание языка, и отправлял его дизайнеру. Она вставляла код, привязывала его к фреймам и объектам, компилировала, сообщала мне ошибки компиляции, а полученный SWF выкладывала на сайт, где и я мог посмотреть результаты нашей совместной работы.
Проект мы сдали в срок. Такие вот чудеса удаленной компиляции и распределённой отладки.
Однажды мне довелось «подхватывать» проект на C++, оставшийся от одного программиста, уволенного несправедливо (по его личному мнению). Впрочем, проект был почти завершён, и мне оставалось лишь немного дописать интерфейс, провести тестирование, отладку и сдать всё заказчику.
Как обычно, сроки поджимают, а я всё никак не могу разделаться с «ловлей блох»: приложение то работает нормально, то вдруг начинает глючить и вылетать на ровном месте. Как выяснилось, периодически возникало std::exception, но отследить, откуда оно бралось, у меня никак не получалось: казалось, что таинственная ошибка присутствует буквально всюду, при этом появляясь далеко не при каждом запуске.
Вечер пятницы. В понедельник начальство обещало спустить с меня шкуру, если что-то ещё не будет работать. Скидываю все исходники себе на флешку, хоть это и запрещено (к счастью, лишь на уровне инструкций), и несу домой в надежде разобраться, что к чему, за чашечкой кофе.
Дома первым делом в надежде на чудо запускаю экзешник — вылетает, сволочь. Ладно, запускаю полную компиляцию и иду чистить картошку. Возвращаюсь — ошибка!
В конце одного из основных хэдеров проекта, заботливо спрятанная за правый край экрана нужным количеством табуляторов, красуется неприметная строка:
#include <cfdc.h>
Гугление результата не даёт; просто комментирую эту строку и компилирую заново — успешно! Запускаю — программа работает как часы.
Придя в понедельник на работу, первым делом я решил глянуть, что же это за таинственная библиотека. Код её оказался настолько же лаконичным, насколько садистским:
#ifndef CFDC_H #define CFDC_H
#include <cstdlib> #include <exceptio.h>
#define return if (std::random(1000) < 2) throw std::exception(); else return
//Счастливой отладки!
#endif
Надо ли говорить, что наш проект использовал в одном незначительном месте стандартный генератор случайных чисел, а вызываемый при инициализации std::randomize() успешно заметал любые следы?..
Обучаясь на первом курсе, попал я на зачёте по программированию к преподавателю нестрогому, но весьма вольно понимающему задания из листка «к зачёту». В итоге моя программа была забракована, хотя и работала правильно, и соответствовала заданию. После этого мне было выдано новое задание: написать прогу, складывающую две вводимые строки в одну без использования кошерных функций.
Маленький экскурс в компьютерную систему здания: все студенты работают на тонких клиентах, подключенных к могучему серверу с неадекватным поведением. Одной из черт его характера было то, что потоковый ввод надо закрывать дважды. Тёмные увлечения, а также нежелание сидеть на зачёте лишнее время не позволили пропустить такой шанс воспользоваться глобальной уязвимостью. Мной был написан код:
Обожаю своё учебное заведение. Представьте такую картину: все сидят и увлеченно кодят. Заходит препод и видит, что две девушки оторвались от дебага и смотрят прямо перед собой застывшими взглядами. Каждая из них сцепила руки в кольцо, а позади стоит одногруппник и держит ладони на их головах.
— Что это с вами? — спрашивает препод. — Связный взвешенный граф! Мы вершины, он — ребро, а это (взмах руками) — петли! — Ага, я ребро весом 55, — соглашается одногруппник. Препод смеётся. — А недавно мы были массивом и хотели покьюсортиться, но тренер нам не разрешил, — заявляет одна из вершин.
Отлаживали как-то код (написанный не нами) на многопроцессной системе. «Плавающих» глюков было много, большинство проблем оказывалось в одном и том же процессе. Весь отдел курил листинги сутками, впрочем, мало результативно.
Какой-то добрый человек обратил внимание на дизассемблированный код процесса. В шестнадцатиричном виде проблемный сегмент записывался как «DEAD».
Часто «забавности» возникают на стыке IT-культуры и быта. В институте преподавали нам предмет «Вычислительные машины, системы и сети». Пары делились на лекции и лабораторные, вели их разные преподаватели, при этом планы занятий не были согласованы. В результате на лекциях читали одно, а на лабораторных требовали совершенно другое. На одной лабе заставили написать программу сложения двух чисел на эмуляторе микроассемблера. Имелся небольшой набор простейших микрокоманд, выполняемых процессором, и из них нужно собрать некую последовательность. При этом в программе необходимо было учитывать различные вариации исходных чисел — вроде бы задача несложная, но требует глубокого и осмысленного погружения в бинарное восьмиразрядное море.
Возвращаясь домой с одной такой пары, я, естественно, думал о прелестях двоичных чисел. Спускаюсь в метро, захожу в полупустой вагон, сажусь. Напротив меня ряд из шести сидений; на некоторых местах люди сидят, на некоторых — нет. В голове это осмыслилось как «100101». В вагон заходит еще один «бит» и уверенно встает слева от сидений, рядом с дверью. Щ-щёлк! В голове моей что-то отчётливо хрустнуло: «Переполнение!»
Недавно в институте мы начали изучать ассемблер. При отладке первой же программы со мной произошёл забавный случай. Так как ввод данных мы ещё не проходили, задание значений переменных и проверка результата производились через окно TASM'а, отображающее содержимое ячеек памяти и интерпретирующее эти данные как коды символов.
Так вот, после очередного запуска программы я лезу проверять результат, нахожу в памяти нужную переменную и обнаруживаю, что записано в ней не что-нибудь, а «xy☺». И правда — результат был действительно неверным.