Переменные JASS.
Подстатья
20 156
38
Забыли написать, что длина имени переменной значительно влияет на производительность в классике
28
Ден94, я люблю когда в меня втыкают тысячу ножей вместе с иглами и прокручивают мои кишки изнутри наворачивая их на шашлычки для бездомных шакалов, мряф ~ </3
22
Ден94, а я больше рок люблю
19
При записи значения выделяется память на количество элементов, равное значению ближайшей сверху степени двойки.
При увеличении массива, его размер подстраивается так, чтобы быть кратным числу X, где X = требуемый размер, округленый вниз до ближайшей степени двойки, но не больше чем 64.
выделение памяти для массивов
void __thiscall GrowableArray_DWORD_::set_capacity(GrowableArray_DWORD_ *this, size_t new_capacity)
{
    size_t items_count_to_copy; // ebp
    DWORD *old_items; // ebx
    DWORD *new_items; // eax
    size_t i; // edx
    DWORD *p_new_item; // eax

    items_count_to_copy = new_capacity;
    old_items = this->items;
    this->capacity = new_capacity;
    new_items = Storm_405_SMemReAlloc(old_items, 4 * new_capacity, DWORD::TypeName, -2, 0x10u);
    this->items = new_items;
    if ( !new_items )
    {
        this->items = Storm_401_SMemAlloc(4 * new_capacity, DWORD::TypeName, -2, 0);
        if ( old_items )
        {
            if ( new_capacity >= this->length )
                items_count_to_copy = this->length;
            for ( i = 0; i < items_count_to_copy; ++i )
            {
                p_new_item = &this->items[i];
                if ( p_new_item )
                    *p_new_item = old_items[i];
            }
            Storm_403_SMemFree(old_items, DWORD::TypeName, -2, 0);
        }
    }
}

size_t __thiscall GrowableArray_DWORD_::get_grow_step(GrowableArray *this, size_t desired_length)
{
    size_t result; // eax
    size_t i; // ecx

    result = desired_length;
    if ( desired_length >= 64 )
    {
        this->grow_step = 64;
        return 64;
    }
    else
    {
        for ( i = desired_length & (desired_length - 1); i; i &= i - 1 )
            result = i;
        if ( !result )
            return 1;
    }
    return result;
}

void __thiscall JassArray::grow_to_fit(JassArray *this, size_t required_length)
{
    DWORD old_length; // eax MAPDST
    DWORD new_length; // esi
    GrowableArray *array; // ebx
    DWORD grow_step; // edi
    DWORD new_capacity; // ecx

    if ( required_length > 8192 )
        required_length = 8192;
    old_length = this->length;
    new_length = required_length;
    if ( required_length <= old_length )
        new_length = this->length;
    array = &this->Array;
    if ( new_length > this->length && new_length > array->capacity )
    {
        grow_step = this->grow_step;
        if ( !grow_step )
            grow_step = GrowableArray_DWORD_::get_grow_step(&this->Array, new_length);
        new_capacity = new_length;
        if ( new_length % grow_step )
            new_capacity = grow_step + new_length - new_length % grow_step;
        GrowableArray_DWORD_::set_capacity(array, new_capacity);
    }
    array->length = new_length;
    if ( required_length > old_length )
        memset(&this->items[old_length], 0, 4 * (required_length - old_length));
}
Локальные массивы с типом наследующим handle просто шикарно отстреливают жопы. При изменении размера будет утечка четырёх байт на каждое значение отличное от null. Поэтому таким массивам обязательно выделять память, гарантировано покрывающим все элементы. А так же при выходе их функции в таком массиве не должно быть значений отличных от null.
Глобальные и локальные массивы работают одинаково. Когда память перевыделяется, то старые елементы копируются в новый буфер, а старый буфер освобождается.
Если перед выходом из функции обнулять все элементы, содержащие agent'ы, то ссылки на таблицу хэндлов тоже не утекут. Тут всё как и с обычными переменными.
запись в массив
void __thiscall JassArray::set_item(JassArray *this, size_t index, int value)
{
    if ( index < this->length )
        this->items[index] = value;
}

void __thiscall ScriptData::set_array_length(ScriptData *this, size_t length, BOOL keep_old_data)
{
    JassArray *value; // eax
    JassArray *old_array; // ecx
    JassArray *new_array; // eax

    if ( this->initialized_type >= TYPE_INT_ARRAY )
    {
        value = this->value;
        if ( value )
        {
            if ( !keep_old_data )
            {
                TSGrowableArray_DWORD_::clear(&value->Array);
                old_array = this->value;
                if ( old_array )
                    old_array->vtable->delete(old_array, TRUE);
                this->value = 0;
            }
        }
    }
    if ( length )
    {
        if ( !this->value )
        {
            new_array = Storm_401_SMemAlloc(sizeof(JassArray), ".\\Instance.cpp", 1362, 0);
            if ( new_array )
            {
                new_array->capacity = 0;
                new_array->items = 0;
                new_array->grow_step = 0;
                new_array->vtable = &JassArray::vtable;
                new_array->length = 0;
                this->value = new_array;
                JassArray::grow_to_fit(new_array, length);
                return;
            }
            this->value = 0;
        }
        JassArray::grow_to_fit(this->value, length);
    }
}

void __thiscall ScriptData::set_array_item_value(
        ScriptData *this,
        int value_type,
        size_t index,
        int value,
        int trust_level)
{
    VAR_TYPE array_type; // eax

    array_type = this->initialized_type;
    if ( array_type >= TYPE_INT_ARRAY && array_type - 5 == value_type || trust_level < 1 )
    {
        ScriptData::set_array_length(this, index + 1, TRUE);
        JassArray::set_item(this->value, index, value);
    }
}
Из багов с массивами, могу припомнить краш при загрузке сохранения, в скрипте которого присутствует массив, размеров больше чем 8191, который происходит из-за неправильной проверки.
фрагмент кода для загрузки массива из потока данных
// ...
    CDataStore::ReadDword(stream, &array_length);
    if ( array_length >= 8192 )
    {
        array_length = 8191;
    }
// ...
Формат изображений, разработанный компанией Blizzard Entertainment.
Статья
12 348