Как я могу получить "ячейку памяти" экземпляра в ActionScript?
Отладчик FlexBuilder покажет вам "ячейку памяти" (или, я могу только предположить, что-то примерно аналогичное) любого экземпляра в области видимости:
расположение памяти отладки http://img.skitch.com/20090827-d5nhcnsja3wcgecif3b2dd5ase.png
Но я хотел бы получить эту информацию в коде (вроде функции Python id
), поэтому я мог бы очень легко проследить, как объекты перемещаются через систему. Например, я мог бы:
trace("Returning", id(foo));
Затем в другом месте я мог бы использовать:
trace("Using", id(foo));
Чтобы оба бита кода имели дело с одним и тем же экземпляром.
Теперь я знаю, что многие классы AS реализуют интерфейс IUID
... Но есть также куча классов, которые не имеют (например, старые старые массивы и объекты), так что это не решило бы мою проблема.
Я понимаю, что я мог бы также обернуть объекты в ObjectProxy
, но это было бы не так идеально.
Ответы
Ответ 1
В реале я советую вам не использовать это слишком много... это очень дорого. Adobe должна создать собственную функцию, чтобы вернуть это нам.
Но на данный момент... попробуйте следующее:
Вам нужно будет вызвать явное принуждение, чтобы получить его!
Потому что, когда вы делаете явное принуждение, вы получаете ошибку вроде этого:
TypeError: Error #1034:
Type Coercion failed: cannot convert [email protected] to flash.utils.ByteArray.
Обратите внимание, что в этой ошибке вы получаете то, что хотите... @1c49d31. Этот хэш подобен идентификатору в распределении памяти.
Я провел много тестов. Этот хэш просто изменяется, когда вы вызываете "новый" (в языках C эквивалентен [[... alloc] init]), а для статических функций и статических свойств распределение происходит немного иначе... в любом случае...
Возвращаясь к Flash, проблема в том, что у нас нет прямого способа получить этот хэш без ошибки.
Но это не очень большая проблема. Все, что вам нужно, это использовать некоторые "try" и "catch",
Вот так:
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 должен быть уверен, что это вызовет ошибку.
Регулярное выражение - это захват последнего @..., который появляется. Поскольку объекты и функции генерируют разные сообщения об этой ошибке. И $состоит в том, чтобы поймать статические объекты, класс и функции, поскольку они не имеют "@" в хэш-памяти и разных зонах в памяти.
Этот маленький код работает так хорошо для меня! Теперь я могу закончить несколько отличных движков, которые я делаю с работой с управлением памятью, слабыми ссылками и идентификатором на основе памяти.
Надеюсь, это поможет вам.
Пока, и удачи, мой друг!
Ответ 2
Решение Diney Bomfim работало как шарм. Я завернул это в класс с именем 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));
Большое спасибо за этот ответ!
Ответ 3
В верхней части моей головы единственный способ, которым я могу это сделать, - использовать объект Dictionary (вы, вероятно, захотите включить слабые клавиши, чтобы избежать каких-либо побочных эффектов), а затем просто возьмите объекты, как вы создавать их и использовать их в качестве ключа к счетчику счетчиков с увеличивающимся числом. Затем вы можете просто посмотреть, существуют ли два объекта в качестве ключей в словаре и если они сравнивают хранящиеся там значения.
Ответ 4
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;
}
Это работает нормально, но требуется уникальный идентификационный номер
Ответ 5
Взгляните на Adobe Scout Debugger - это гораздо более мощный отладчик
http://gaming.adobe.com/technologies/scout/
http://www.adobe.com/devnet/scout/articles/adobe-scout-getting-started.html
Ответ 6
AFAIK нет способа получить значение, которое отладчик показывает вам во время выполнения.
Общий снимок в темноте, но я думаю, вы можете использовать сравнение ===, чтобы определить, являются ли два объекта одним и тем же объектом (в отличие от ==, который сравнивает значения объектов). Но я мог бы ошибаться.