PDA

Просмотр полной версии : crash ошибка при больших индексах массива


microed
24.08.2009, 22:47
Согласно документации, максимальное число элементов в одномерном массиве: 2^32=4294967296. Мне нужен весь диапазон индексов. Пробуем:


var arr:Array=new Array();
arr[0]=false;
// ... и др.
arr[2147483647]=true;
arr[2147483648]=true; // с этого индекса начинаются проблемы
arr[3273124597]=true;
arr[4294967295]=true;


Cобственно проблемы:
arr.splice(0); // вызывает неуправляемую утечку памяти с crash ошибкой плейера:

Add-ons: {972ce4c6-7e08-4474-a285-3208198ce6fd}:3.0.13
BuildID: 2009073022
CrashTime: 1251135034
InstallTime: 1249678458
ProductName: Firefox
SecondsSinceLastCrash: 1950
StartupTime: 1251134999
Theme: classic/1.0
Vendor: Mozilla
Version: 3.0.13
---------------------------------------

Подозрительный момент: во Flex'овом отладчике по watch видно, что все элементы, начиная с индекса 2147483648 он [отладчик] в 'Expressions' окне отрисовывает уже без квадратных скобок, т.е. выглядит это так:

[2147483647]=true;
2147483648=true;
3273124597=true;
4294967295=true;

Однако обращения к элементам с этими индексами проходят удачно и значения считываются.

Использую SDK 3.3.0.
Объем памяти: 2Гб.

Это баг или я что-то не так понимаю?

wvxvw
24.08.2009, 22:57
trace(2147483648, int.MAX_VALUE);
Интересно, в какой ситуации нужен такой большой массив?
Да, и это, ссылку на документацию пожалуйста, как это свойсто length типа int будет вам возвращать такие числа?

microed
24.08.2009, 23:15
trace(2147483648, int.MAX_VALUE);
Да, и это, ссылку на документацию пожалуйста, как это свойсто length типа int будет вам возвращать такие числа?

Хм. Да нормально возвращают. И отладчик, и трассировщик::

var tn:Number=arr.length;
trace(tn);

udaaff
24.08.2009, 23:25
Да, и это, ссылку на документацию пожалуйста, как это свойсто length типа int будет вам возвращать такие числа?
Не int, а uint.

microed
25.08.2009, 00:07
http://livedocs.adobe.com/flex/3/html/help.html?content=Part6_ProgAS_1.html

wvxvw
25.08.2009, 00:31
@ udaaff:

Array(numElements:int = 0)
Lets you create an array of the specified number of elements.
То что у length стоит тип uint, это для проформы, на самом деле int.
@ microed:
Это ссылка на титульную страницу...
Вам на самом деле сюда надо было сначала смотреть:
http://livedocs.adobe.com/flex/3/langref/Array.html

udaaff
25.08.2009, 00:40
@ wvxvw
Indexed arrays use an unsigned 32-bit integer for the index number. The maximum size of an indexed array is 232 - 1 or 4,294,967,295. An attempt to create an array that is larger than the maximum size results in a run-time error.
Там int, тут uint.. не понятно.

microed
25.08.2009, 01:00
@ udaaff:

То что у length стоит тип uint, это для проформы, на самом деле int.
@ microed:
Это ссылка на титульную страницу...
Вам на самом деле сюда надо было сначала смотреть:
http://livedocs.adobe.com/flex/3/langref/Array.html

Ну хорошо, смотрим..
"Property Detail
length:uint
A non-negative integer specifying the number of elements in the array." И далее по тексту..

"The uint data type is stored internally as a 32-bit unsigned integer and comprises the set of integers from 0 to 4,294,967,295"

Пока всё в документации указывает на index max = 4,294,967,295. Чем докажете, что это всё "для проформы"? Они где-то оговорились или покаялись?

wvxvw
25.08.2009, 01:35
Хм... а вообще - интересный момент... не смотря на то, что аргумент у Array() задан как int, он вполне принимает и бОльшие значения...
Возможно зависит от версии плеера, потому что у меня ваш код не вызывает никаких исключений.

microed
25.08.2009, 01:43
Для прогонки использую плагин для firefox v10.0 r12. На нем и проявилось..

udaaff
25.08.2009, 01:45
var array:Array = new Array(0xFFFFFFFF); // все нормально
var array:Array = new Array(0xFFFFFFFF + 1);
RangeError: Error #1005: Array index is not a positive integer (4294967296).
at Error$/throwError()
at Array()
at Test()[F:\workspaces\Flex Builder\test\src\Test.as:13]

upd:
Код из первого поста, никаких ошибок не вызывает.

wvxvw
25.08.2009, 02:40
Подозрительный момент: во Flex'овом отладчике по watch видно, что все элементы, начиная с индекса 2147483648 он [отладчик] в 'Expressions' окне отрисовывает уже без квадратных скобок, т.е. выглядит это так:

[2147483647]=true;
2147483648=true;
3273124597=true;
4294967295=true;

Однако обращения к элементам с этими индексами проходят удачно и значения считываются.

Использую SDK 3.3.0.
Объем памяти: 2Гб.

Это баг или я что-то не так понимаю?

Просто кода идет обращение к динамическим свойствам, то строка и число взаимозаменимы, а поскольку массив динамический объект, то при попытке обратится к свойству, которое не может быть индексом, имя свойства будет расценено как строка, вот поэтому вы и наблюдаете то, что наблюдаете.
Но, пока не понятно, баг ли это конкретной версии плеера или документации. Быстрый поиск по списку багов ничего такого не нашел... предлагаю попробовать в другой версии плеера (есть и десятка по-новее, и можно последнюю девятку), если там такого не наблюдается - значит баг плеера...

EDIT:
// SDK 4.0 4904
// SDK 4.0 head revision (9546)
var arr:Array = [];
arr[uint.MAX_VALUE + 2] = true;
trace(Capabilities.version);
trace(arr[uint.MAX_VALUE + 2], uint.MAX_VALUE, arr.length);
//WIN 10,0,22,87
//true 4294967295 0
// Flash IDE
var arr:Array = [];
arr[uint.MAX_VALUE + 2] = true;
trace(Capabilities.version);
trace(arr[uint.MAX_VALUE + 2], uint.MAX_VALUE, arr.length);
//WIN 9,0,115,0
//true 4294967295 0

microed
26.08.2009, 17:18
var array:Array = new Array(0xFFFFFFFF); // все нормально
var array:Array = new Array(0xFFFFFFFF + 1);
RangeError: Error #1005: Array index is not a positive integer (4294967296).
at Error$/throwError()
at Array()
at Test()[F:\workspaces\Flex Builder\test\src\Test.as:13]

upd:
Код из первого поста, никаких ошибок не вызывает.

Сам код создания большого массива ошибок не вызывает. Ошибку вызывает зачистка этого массива. Теперь попробуй сделать:

arr.splice(0); // here bug

Добавлено через 16 минут
Сделал тест код с контролем текущего времени и использованной памяти.

К примеру, простая вещь:

var arr:Array=new Array();
arr[10000000]=true;
arr.splice(0);

вызывает кратковременный всплеск потребляемой памяти на ~38MB

а с увеличением индекса на порядок:

var arr:Array=new Array();
arr[100000000]=true;
arr.splice(0);

получаем всплекс на ~382MB ..ну и т.д. Использование памяти можно посмотреть и в диспетчере задач - показывает тоже самое.

Видно, что временное потребление памяти растет линейно. Что уж говорить про максимальный индекс [4294967295].

Насчет времени: когда производится очистка массива, выполнение пользовательского кода останавливается - тормозится даже Timer и листинеры.
А порядок задержки опять же зависит от наибольшего используемого значения индекса, даже если элемент в массиве один.


В общем, не баг это, а отвратно написанная внутренняя системная функция очистки массива.

wvxvw
26.08.2009, 18:54
Еще раз про максимальный индекс - другий более простой способ, чо это int.MAX_VALUE:
var a:Array = [];
a[uint.MAX_VALUE] = true;
a.length = 0;
trace(a[uint.MAX_VALUE]); // true
что еще рз подтверждает, что значения больше int.MAX_VALUE не могут быть индексами в массиве.

microed
26.08.2009, 20:53
..что еще раз подтверждает сырость продукта, ибо если "значения больше int.MAX_VALUE не могут быть индексами в массиве", то мы должны ясно и недвусмысленно получать в дыню:

RangeError: Error #1005

ан нет...