• Возвращение Angelusa (часть 2)

  • Взломан профиль в одноклассниках, требуется для доступа отправить смс. Другой вариант попасть на страничку есть?

  • Оговорюсь сразу же - трудноуловим он может быть только для меня. В силу того, что он мог возникнуть именно в моем релизе Rad Studio, именно на моей системе, именно на моей RAM или в силу звезд, светивших надо мной в эти (сумме) несколько месяцев, что я его ловил.

    Задача была нетривиальной - font-генератор для движка на основе стандартных шрифтов Das Windows '45.

    В основу легла идея того, что можно взять TBitmap и с помощью TextOut-а все туда вывести построчно. И сохраниться.

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

    Итак, задача - записать номер символа в юникоде и 2 пары целых чисел в файл для каждого символа. Для этого я создал массив записей вида

    TLitera = record
       x1,y1,x2,y2: Integer;
    end;

    Ваш покорный слуга вздумал играться с XML через TXMLDocument. Честно признаюсь, два месяца я грешил только на него. Говорить о том, сколько я перебрал комбинаций параметров и прочего - попусту забивать ленту.

    Прога падала с AV при создании узла (т.е. элемента <char></char>) с символом. А если быть точном - на 127-ом. Это магически правильное число и стало причиной двух месяцев безуспешных поисков - я думал, что XML стандарта MSXML просто физически не может держать больше 128 узлов в 1-ом узле. Начал писать файл каждые 128 символов, создавал новые ноды под каждые 128 символов - тщетно, падения были все более бессмысленными. Код ушел в тень на несколько месяцев.

    Сегодня я открыл этот старый код и начал думать. Сказать, что я дебаг-мастер - сильно покривить душой, но я и не новичок. Call stack был олицетворением скомпилированной проги на brainfuck-е, а падение настолько не аргументированным (CPU просто выдавал строку leave), что я понял - так больше нельзя.

    Переписал сохранение на обычный TStringList. И тут меня ожидал коварный удар поддых. Бессмысленные падения на сохранении не прекратились. Был отключен коварный TSaveDialog (который довольно подозрительно отражал свою деятельность в колл стэке), было вырублено все, что только можно - увы, прога падала и падала. Более того - она падала даже при таком коде:

    for i := i1 to i2 do
      strdata.Add(IntToStr(i) + ' ');

    примерно на 43 итерации.

    Тут я начал понимать, что дело мое плохо - место имеет какая-то какашка с памятью и начал искать все те места, где я мог подгадить. И о чудо! Отключив заполнение массива записей TLitera я не получил AV. Вот тут я крепко задумался.

    Что такого в массиве на тысячу с чем-то элементов? Посмотрел на Integer. В голове мелькнуло сомнение, которое подтвердилось - Integer=LongInt, значит имеем 4 байта. Каждая запись - 16 байт, массив - чуть менее 20 килобайт. Поменял значение на ShortInt - все заработало.

    Неужели для delphi массив записей на 20 килобайт является критическим и засирающим память?!






  • Возвращение Angelusa (часть 2)

  • Взломан профиль в одноклассниках, требуется для доступа отправить смс. Другой вариант попасть на страничку есть?