Даже в определениях идиотизма встречается идиотизм.
Цитата:
Идиотизм — устаревшее название идиомы
Идиома в программировании — понятие близкое к понятию шаблона проектирования. Идиомы представляют собой шаблоны проектирования, учитывающие специфику конкретного языка программирования и потому не универсальные. Это хорошие решения проектирования для конкретного языка или программной платформы.
Идиома в программировании — понятие близкое к понятию шаблона проектирования. Идиомы представляют собой шаблоны проектирования, учитывающие специфику конкретного языка программирования и потому не универсальные. Это хорошие решения проектирования для конкретного языка или программной платформы.
Идиотизмы: не ByteArray а мусорка
для понимания материала необходимы следующие знания:
flash.utils.ByteArray
сижу я, значит, пишу обновлении для своей крипто-библиотеки, и случайно вывожу на экран 2 результата от 2 запусков PNGEncoder.
первый вариант 100% совпадает с оригиналом, а второй был слегка искажён. я сперва не сообразил, что произошло, а потом пришёл в состояние шока. решил добавить ещё парочку результатов, и получил, ещё более искажённые результаты.
начал искать искать ошибки у себя в коде: переиспользование переменных; проверял везде ли чиститься память; заменял одни вызовы другим, но результат становился чаще хуже, чем лучше.
на протяжении всех 10 часов паники я общался с wvxvw, и мы вместе пытались понять причину, но не ничего не выходило.
в конце концов в один из блоков я вставил код проверки на записанное значение в ByteArray. и оказалось, что там на 88731 индексе уже записано число отличное от 0.
глаза мои вылезли на орбиту: ведь этот массив был создан всего 2мя строчками выше, и в него ничего не писалось кроме одного числа в нулевой индекс! то есть фактически он был пуст.
передвинув проверку на строчку выше я удивился ещё больше, так как не только trace оказался чист, но и картинки отобразились корректно.
немного поигравшись с перемещением срок, я убедился, в зависимости бага от положения строк.
выяснилось следующие: при определённых обстоятельствах бинарник оказывался не девственно чистым. обстоятельства такого поведения обнаружить не удалось. но решение найдено таки было.
чистота бинарника зависит от первой операции проводимой с ним!
если первой операцией будет write, то в массиве может оказаться мусор. но если первой операцией задать ему нужную длину, то на протяжении всей длинны будут записаны только нули.
var b:ByteArray = new ByteArray(); b.writeUnsignedInt( value ); b.length = 1024; // может попасться мусор
Всего комментариев 31
Комментарии
![]() ![]() |
|
![]() ![]() |
|
TimID, как много Вы знаете о работе виртуальных машин =)
|
![]() ![]() |
|
![]() ![]() |
|
Будет весело если баг в винде...
Кстати сейчас попробую в убунте. |
![]() ![]() |
|
В IE в 10.0 все нормально.
В standalone 10.0 - баг В FF 10.0 - баг |
![]() ![]() |
|
Просто для общего сведения, Ubuntu Lucid - никаких визуальных артефактов...
|
![]() ![]() |
|
win7, 10.1
во всех браузерах (ie, opera, ff, chrome, safari) и стендалоун плеере все ок |
![]() ![]() |
|
TimID, теперь Вы должны уже начать догадываться как работают виртуальные машины.
|
![]() ![]() |
|
Win7
standalone 10.0 баг IE 10.1 норм Chrome 10.1 норм может в 10.1 баг поправили? |
![]() ![]() |
|
Возможно, я лично совсем недавно до последней версии обновилсо)
|
![]() ![]() |
|
BloodHound, верно ли товарищ понимает как работают в. машины?
|
![]() ![]() |
|
я в браузере не тестил.
первая картинка это оригинал. она создаётся сразу. остальные создаются после того как произойдёт их перегон в пнг, а потом loadBytes |
![]() ![]() |
|
Помогите воспроизвести появление мусора.
Код:
package { import flash.display.Sprite; import flash.events.Event; import flash.utils.ByteArray; import flash.net.SharedObject; public class Main extends Sprite { private var b:ByteArray; public function Main():void { if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); // b = new ByteArray(); fillData(b, 0xffffff00, 0, 5000, "b1"); b.clear();// чистим предыдущий филл fillData(b, 0x000000ff, 4, 5000,"b2"); } private function fillData(b:ByteArray, value:uint, offset:uint, max:uint, name:String):void { for (var i:int = 0; i < max; i++) { b.writeUnsignedInt(value); b.position += offset;//пропуск позиций, дабы не забить возможный мусор } var so:SharedObject = SharedObject.getLocal(name, "/"); so.data.b = b; so.flush(); } } } ЗЫ файлы смотреть пока плеер не выключен. ЗЫ Непонятно, так непонятно, фик с ним. |
|
Обновил(-а) alexcon314 01.07.2010 в 13:55
|
![]() ![]() |
|
6. запись в бинарник происходит по средстави Virtual Memory API. может быть и это и играет роль.
|
![]() ![]() |
|
мне таки удалось собрать простой пример, в котором наблюдается бага!!! УРА!
package { import flash.display.Sprite; import flash.utils.ByteArray; public class test extends Sprite { /** * Constructor */ public function test() { super(); // запускаем многократные тесты for ( var i:uint = 0; i<10; i++ ) { trace( '================== test ' + i ); binary_test(); } } private static const LENGTH:uint = 5e3; private static function binary_test():void { // создаём новый бинарник var bytes:ByteArray = new ByteArray(); bytes.writeUnsignedInt( 10 ); // делаем запись bytes.length = LENGTH; // меняем длинну // проверяем что у нас лежит в бинарнике var i:uint = 4; do { if ( bytes[ i ] != 0 ) { trace( 'index: ' + i + ', value: ' + bytes[ i ] ); } } while ( ++i < LENGTH ); // заполняем бинарник i = 4; do { bytes.writeInt( i ); i += 4; } while ( i < LENGTH ); bytes.clear(); // чистим } } } |
|
Обновил(-а) BlooDHounD 01.07.2010 в 15:36
|
![]() ![]() |
|
Отлично. То что нужно. Кстати, вертелась мысль - закомментить clear(), Попробовал, трейсов стало заметно меньше. Всего в двух тестах последних и понемногу совсем.
|
|
Обновил(-а) alexcon314 01.07.2010 в 15:57
|
![]() ![]() |
|
Если LENGTH = 5е5 и clear() убрать все вообще чисто
![]() |
![]() ![]() |
|
Как ты угадал с 5е3?
5е2-чисто 5е4-чисто 5е5-чисто 5е6-чисто |
![]() ![]() |
|
Всплыло...
Не ахти что, но все же. Вобщем, механизм выделения памяти под массив байтов примерно такой: Код:
//баги нет var b:ByteArray = new ByteArray();// выделяется 4096 байт чистой памяти. b[0] = 10; b.lenght = 4096;//это ни на что уже не влияет, память чистая изначально. Даже если сделать длину < 4096 - в памяти чисто, опять же потому, что выделена она была таковой. 4096 (0х1000) - это не что иное, как размер страницы памяти в х86-системах. Собственно, плеер и выделяет ее как раз по-странично. Что будет, если взять число > 4096? Например, 5000? Ну, как и в первом случае после new ByteArray(); выделится 4096 чистой памяти, произойдет запись (массив инициализирован!). А вот дальше.. тут понятное дело, плеер вынужден будет "прихватить" некоторе количемтво ячеек из другой страницы.., но занулять "прихваченные" байты он не будет. Вроде, все логично. Возьмем целое кратное 4096, ну, скажем 2*4096. Опять видим мусор, причем на второй странице. Однако, если делать 10*4096 (20*, 30*...), то ситуация значительно лучше! Мусора практически нет. Почему "практически", а не точно? Видимо, плеерный менеджер памяти, при не особо загруженной памяти не скупится выделять чистые странички. Но, тем не менее, может и грязную подсунуть. Почему же, если мы делаем сначала b.lenght = <что-то большее нуля>; мусора нет? Ну, тут просто. Менеджер видит, свежий массив (не инициализированный!) с точно заданными размерами и у него "развязаны руки" - он может запросто выделить память заново (ссылка b может быть отмаплена на совсем другой адрес), почистить ее и предоставить для использования. ЗЫ. Ясен пень, все на деле сложнее, но примерно что-то похожее... |
|
Обновил(-а) alexcon314 17.11.2010 в 16:35
|
![]() ![]() |
|
ну как бы и так всё понятно )
|
![]() ![]() |
|
win7x64 везде пучком и без багов
![]() |
![]() ![]() |
|
у меня не пучком.
|
Последние записи от BlooDHounD
- Обновление blooddy_crypto.swc до версии 0.5.1 (31.03.2016)
- Кто не успел - тот опоздал (19.04.2011)
- Обновление blooddy_crypto.swc до версии 0.3.1 (29.11.2010)
- blooddy_crypto.swc теперь умеет JSON (13.10.2010)
- Загадочный CommaExpression (06.09.2010)