И снова про память. Оперативную

Aug 25, 2006 17:04

Память - основа всего. Но начнём издалека.

Есть Роснефть, которая недавно вылезла на IPO и по её акциям попёрла куча операций: биржевые спекулянты суетятся, сама Роснефть хочет отчёты, акционеры хотят выписки, внимание повышенное, жизнь кипит.

Реестр акций Роснефти ведёт некая организация-регистратор. И вот эта организация начинает косячить с отчётами. Регулярную отчётность она до поры исправно поставляла, а тут начала забывать. При напоминании - тормозить, бормотать что-то в трубку, оправдываться, стрелки косить. Обстановка накаляется. Начинаются звонки дирекции, письма, неприятные визиты и над регистратором явственно сгущается тёмное облако, пахнущее крупной разборкой.

А почему так получилось? А потому, что регулярная, да и вся прочая отчётность формируется у них в специальной программе, которая тащит на себе технические функции ведения реестра акционеров. Программа эта тяжеловатая, с несовременным интерфейсом, но как ни крути, а по имеющимся функциям лучше ничего нету. И жили с ней нормально, пока не произошло банальное событие - перешли на новую версию. И с отчётами начинаются сложности - через два раза на третий валится загадочная ошибка, которую программа диагностирует максимально абстрактно - "йух его знает, что там, но всё упало". Или ошибка не валится, но из двух запрошенных отчётов формируется один. Правда, бывает, что отчёты нормально проходят, но минуту спустя программный сервер заводит знакомую песню "йух его знает...", но уже всем пользователям подряд и в конечном счёте зависает.

А почему программа начала так себя вести? А потому, что интерфейс с СУБД устроен так, что ты даёшь СУБД буфер, а СУБД в него пишет. А то, чтобы буфер был достаточного размера - оно полностью на твоей совести. СУБД же работает согласно своим собственным словарям и если она считает, что бурундук - птичка, она-таки птичку из него сделает. Вот написано у неё - 3 байта, так она 3 байта и запишет, а какой у буфера реальный размер - так это не барское дело считать.

Вот и получилось, что в базе поменяли структуру индекса, а класс, инкапсулирующий работу с ним - забыли. И он продолжал подавать буфер на 1 (один!) байт меньше, чем надо. В результате портился один байт стека, в котором лежал указатель на область динамической памяти, которая потом пыталась освободиться по некорректному уже указателю, что разрушало кучу (heap). Ну а разрушенная куча - это верный путь к самым непредсказуемым ошибкам.

Последствия укороченного на единственный байт буфера - в первых абзацах, зацените.

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

Реальные же дятлы - это, конечно, разработчики программы, в число которых вхожу и я персонально. Много уже лет назад я говорил, что наши классы индексов, без автогенерации по структуре БД - мина, на которой подорвёмся рано или поздно. А уж универсальные классы индексов - вообще звиздец. Но выбить время на реформы - не выбил.

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

А сегодня я написал собственный менеджер кучи, роль которого в поиске врага была решающей. Путём чудовищного перерасхода памяти, он превращает подавляющее большинство некорректных обращений к куче в access violation и отладочные события, которые легко отслеживаются при отладке. Конфетка вышла! Изумительно простая и эффективная. Делюсь со всеми желающими совершенно бесплатно.

программирование

Previous post Next post
Up