Как я могу получить «расположение памяти» экземпляра в ActionScript? - PullRequest
32 голосов
/ 27 августа 2009

Отладчик FlexBuilder покажет вам «область памяти» (или, я могу только предположить, что-то примерно аналогичное) любого экземпляра в области видимости:

debugger memory location

Но я бы хотел получить эту информацию в коде (вроде функции id в Python), чтобы я мог очень легко отслеживать, как объекты перемещаются по системе. Например, я мог бы иметь:

trace("Returning", id(foo));

Тогда где-нибудь еще я мог бы использовать:

trace("Using", id(foo));

Чтобы убедиться, что оба бита кода имеют дело с одним и тем же экземпляром.

Теперь я знаю, что многие классы AS реализуют интерфейс IUID ... Но есть также несколько классов, которые этого не делают (например, простые старые массивы и объекты), так что это не решило бы мой проблема.

Я понимаю, что я мог бы также обернуть объекты в ObjectProxy, но это также было бы далеко не идеально.

Ответы [ 6 ]

59 голосов
/ 28 мая 2010

На самом деле я советую вам не использовать это слишком много ... это очень дорого. Adobe нужно создать собственную функцию, чтобы вернуть это нам.

Но пока ... попробуйте это:

Вам понадобится явное принуждение, чтобы получить его! Потому что когда вы делаете явное принуждение, вы получаете ошибку, подобную этой:

TypeError: Error #1034: 
Type Coercion failed: cannot convert Main@1c49d31 to flash.utils.ByteArray.

Обратите внимание, что в этой ошибке вы получаете то, что хотите ... @ 1c49d31. Этот хеш похож на идентификатор в распределении памяти.

Я сделал много тестов. Этот хэш просто меняется, когда вы вызываете «new» (в языках C эквивалентно [[... alloc] init]), а для статических функций и статических свойств распределение происходит немного по-другому ... в любом случае ...

Возвращаясь к Flash, проблема в том, что у нас нет прямого способа получить этот хэш без ошибки.

Но это не очень большая проблема. Все, что вам нужно, это использовать "попробовать" и "поймать" Как это:

try
{
    ByteArray(anyObjectToKnowItAllocationHash);
}
catch (e:Error)
{
    trace(e);
}

И вуаля! Вы получите хэш без результата в ошибке! После этого я сделал более изощренный способ ... Попробуйте это:

var memoryHash:String;

try
{
    FakeClass(anyObjectToKnowItAllocationHash);
}
catch (e:Error)
{
    memoryHash = String(e).replace(/.*([@|\$].*?) to .*$/gi, '$1');
}

internal final class FakeClass { }

Небольшое объяснение по этому поводу: FakeClass должен быть уверен, что это вызовет ошибку. Регулярное выражение должно захватывать последние @ ..., которые появляются. Потому что объекты и функции генерируют разные сообщения об этой ошибке. А $ - это перехват статических объектов, классов и функций, потому что у них нет «@» в хеш-памяти и различных зон в памяти.

Этот маленький код прекрасно работает для меня! Теперь я могу закончить некоторые замечательные движки, которые я создаю, которые работают с управлением памятью, слабыми ссылками и ID на основе памяти.

Надеюсь, это поможет вам.

До свидания, и удачи, мой друг!

11 голосов
/ 03 декабря 2011

Решение Дини Бомфима сработало как шарм. Я обернул это в класс с именем DebugUtils в функцию с именем getObjectMemoryHash.

package
{
    public class DebugUtils
    {
        public static function getObjectMemoryHash(obj:*):String
        {
            var memoryHash:String;

            try
            {
                FakeClass(obj);
            }
            catch (e:Error)
            {
                memoryHash = String(e).replace(/.*([@|\$].*?) to .*$/gi, '$1');
            }

            return memoryHash;
        }
    }
}

internal final class FakeClass { }

Тогда я мог бы использовать эту функцию из любой точки и отследить ее так:

trace('myObj', DebugUtils.getObjectMemoryHash(myObj));

Большое спасибо за этот ответ!

6 голосов
/ 27 августа 2009

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

5 голосов
/ 02 июня 2012
private static var _uids:Dictionary = new Dictionary(true);
private static var _cter:uint = 1;

public static function getObjectMemoryHash(obj:*):uint {
   var ret:uint = _uids[obj];
   return (ret == 0) ? (_uids[obj] = _cter++) : ret;
}

Это нормально работает установщик, но требует уникальный идентификационный номер

2 голосов
/ 17 сентября 2013

Взгляните на Adobe Scout Debugger - это гораздо более мощный отладчик

http://gaming.adobe.com/technologies/scout/

http://www.adobe.com/devnet/scout/articles/adobe-scout-getting-started.html

1 голос
/ 28 августа 2009

AFAIK нет способа получить значение, которое отладчик показывает вам во время выполнения.

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

...