Комментарии 42
Friday всего 6 символов, даже если бы выводилось «01» вместо «1», то краша всё равно не было бы.
А вот 2ое или 3ье августа, это да.
1е августа 2015- суббота.
Saturday = 8символов.
Да еще и название месяца не короткое July(4), а длинное August(6). Про September(9) я вообще молчу
Например потратить неделю на отладку. Почти всегда это непозволительная роскошь.
Насколько я помню, для такого рода систем даже вводят формальные доказательства корректности программ. Что очень накладно по времени.
и его можно найти, если копнуть достаточно глубоко.
Самого главного не усвоил — копать надо экскаватором или на худой конец лопатой. Для поиска причины падений обычно используют core-dumps / отладчик / стек-трейс. Такая элементарная ошибка была бы видна на первом же трейсе — segfault во время вызова printf (использования printf при разработке на c++ — вообще отдельный вопрос).
Искал я причину в интернете долго (два месяца) — но в итоге догадался декомпилировать код сервера, чтобы посмотреть где же он падает. Выяснил, что падает в хранимой процедуре. Декомпилировать хранимую процедуру было куда сложнее: она была шифрованной, а программа для расшифровки — шароварной. А триальном же режиме программа расшифровывала лишь первые 200 байт — и в них не вмещался даже заголовок хранимки.
Что мешало программу купить — уже не помню. То ли были серьезные подозрения на кота в мешке, то ли не было возможности перевести автору деньги, то ли денег не было, но наверное просто жаба душила платить довольно крупную сумму за программу для разовой работы с неизвестной заранее пользой. Коллега за ночь взломал защиту той программы, и удалось продолжить исследования.
Выяснилось, что все билды в TFS лежат в одной таблице, первичным ключом билда при этом является его имя. И это самое имя присваивается билду аж три раза. Сначала создается запись в БД с автоинкрементным числом вместо имени, потом это число заменяется на временное имя вида BuildDefinitionName.20150730.5
Третий раз имя билда меняется уже в процессе самого построения, в процессе выполнения задачи AssignBuildName.
Второе имя билда еще может промелькнуть в интерфейсе — а в случае серьезных проблем со сборкой даже остаться там — но первое имя билда увидеть практически невозможно, поэтому его существование стало сюрпризом.
Теперь в чем была проблема. Дело в том, что мы присваивали нашим билдам имена на основе нашего собственного автоинкрементного счетчика версий. Причем, поскольку мы мигрировали с другой системы построения, а не начинали проект сразу в TFS — наши номера билдов начинались где-то с 1900. И, спустя полгода после миграции, внутренний счетчик билда TFS дошел до этой цифры. Тогда-то все и началось!
Когда причина проблемы стала ясна, решилась проблема очень просто: я просто стал добавлять префикс «b» всем билдам, плюс добавил его всем старым билддам в БД простым UPDATE. После этого все заработало. С тех пор я полюбил смотреть в чужие исходники, и часто обращаюсь именно к этому способу решения мистических проблем…
К сожалению, подобного рода ситуации встречаются с каждым программистов, даже при использовании уже отточенной для себя технологии.
Игра, в игре есть арена. Раньше все работало хорошо, потом вдруг в некоторых на первый взгляд произвольных случаях вызов на арену перестал работать.
Отправляется заявка на сервер, в ней передается время. Если в течении минуты никто не вызвал игрока — то заявка снимается. Долго не мог понять, дело оказало в следующем: оказалось что UTC time в один и тот же момент времени возвращает разные значения. В зависимости от версии iOS. На старых iOS был еще перевод на летнее время, потом этот балбес Медведев начал крутить стрелки, вышла новая версия, потом еще из думы руки приложили переведя стрелки еще раз. Естесвенно программисты в Apple это предугадать не могли и каждая версия iOS переходит (или не переходит) на летнее время по разному. В результате всякие уведомления и напоминания на старой версии приходят с разницей в час, ну и в игре у нас заявка приходила уже устаревшей (на час) и сразу снималась. То, что GetTimeUTC может вернуть разные значения и его нельзя использовать для синхронизации — для меня было открытием.
Рассказал жене — они грит на работе у них программисты сталкивались с похожим багом, тоже нелестно отзывались о крутителях стрелок.
Отправляется заявка на сервер, в ней передается время. Если в течении минуты никто не вызвал игрока — то заявка снимаетсяТогда вопрос – заявка снимается кем именно? Самим клиентом? или «тиражирующим» сервером?
Если самим клиентом – тогда в чём проблема, в пределах одного клиента время будет правильным.
Если сервером – то снова встаёт вопрос о том, зачем нужно передавать время с клиента.
char buffer[48];
sprintf(buffer, "insert into aaa(f1,f2,f3) values(%d,%d,%d)", index1, index2, index3);
Он не учитывал, что 32битный инт в десятичном представлении мог занимать до 11 символов (-2147483647).
У меня тоже был забавный баг с переполнением буфера.
Делали мы в начале 2000-х цифровую городскую АТС на 10 тыс. абонентов. Большая часть системы работала на серверах, но еще было некое "ядро", которое непосредственно управляло всяким железом. Вот это ядро я как раз и писал. Крутилось оно на промышленом компьютере с 1МБ оперативы и аж целых 4МБ флэша. Операционка QNX4. Вот туда надо было впихнуть упомянутое ядро, урезанную базу абонентов (таблицу: номер телефона, список доступных услуг, количество потраченых минут) и еще несколько нужных сервисов, короче, ресурсов катастрофически не хватало. Поэтому мне пришлось всячески поизвращаться, чтобы все это поместилось в те самые 1М оперативки и 4М флэша. Например, пришлось писать менеджер памяти для мелких объектов, т.к. с библиотечным память быстро дефрагментировалась и ядро крэшилось с аут ов мемори. "База данных" тоже была самописанная и представляла собой хэш таблицу.
И вот, наконец, мы дожили до госприемки - мы смонтировали нашу АТС на настоящей телефонной станции, куда приехала комиссия из министерства связи. Все четко и без сбоев работало. Для проверки комиссии предоставлен телефон подключенный к нашей АТС.
И вот тут женщина из комиссии набирает от балды какой-то номер и мое ядро крэшится, но через секунд 10 перезапускается. Женщина кричит: Нет гудка! Нет гудка! Подходит председатель комиссии, слушает - гудок есть. Она опять набирает этот же номер и снова кричит: Нет гудка. Как только ядро перезапускается, я быстренько блокирую в базе этот номер (вижу его в логах), теперь на него нельзя звонить и с умным видом говорю, что такого номера не существует, мол поэтому нельзя дозвониться. Комиссия этим удовлетворяется. Приемку мы прошли.
Потом, в спокойной обстановке, я воспроизвожу эту ошибку. Оказалось, что я ошибся на 1 байт при вычислении размера хэш таблицы. Набираемый той женщиной номер попадал как раз в последний слот таблицы и количество минут разговора как раз писалось в тот байт за пределами блока памяти выделенного под таблицу, затирая там что-то критическое. Причем, это был единственный номер из возможных 10 тысяч, который попадал в конец таблицы. Т.е. вероятность набрав номер от балды вызвать крэш была 1/10000. Она смогла.
Когда программа падает только по средам