How can I get an instance's "memory location" in ActionScript?
Asked Answered
D

6

32

FlexBuilder's debugger will show you the "memory location" (or, I can only assume, something roughly analogous) of any in-scope instance:

debugger memory location

But I'd like to get this information in code (sort of like Python's id function), so I could very easily trace how objects move through out the system. For example, I might have:

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

Then somewhere else I could use:

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

To make sure both bits of code are dealing with the same instance.

Now, I know that many AS classes implement the IUID interface... But there are also a bunch of classes which don't (plain old arrays and objects, for example), so that wouldn't solve my problem.

I realize that I could also wrap objects in an ObjectProxy, but that would be less than ideal as well.

Dowland answered 27/8, 2009 at 19:21 Comment(1)
you may wanna have a look at this: https://mcmap.net/q/454084/-object-reference-as-string/…, which quite what branden proposed ... :)Harbard
J
60

In realy I advise to you don't to use this too much... it is very expensive. Adobe need to create a native function to return this to us.

But, for now... try this:

You will need to cause a explicit coercion to get it! Because when you make and explicit coercion you get an Error like this:

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

Note that in this error you get what you want... the @1c49d31. This hash is like an ID in the memory allocation.

I did a lot of tests. This hash just change when you call a "new" (in C languages is equivalent to [[... alloc] init]) and for static functions and static properties, the allocation occurs a little different... anyway...

Backing to Flash, the problem is we don't have a direct way to get this hash without an Error.

But this is not a realy big problem. All that you need is to use some "try" and "catch" Like this:

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

And voila! You will get the hash without result in an Error! After this I did a more refinated way... Try this:

var memoryHash:String;

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

internal final class FakeClass { }

A little explain about this: The fakeClass is to be sure about this will generate an Error. The RegularExpression is to capture the last @... that appear. Because Objects and Functions generate different messages on this Error. And the $ is to catch the Static Objects, Class and Functions, bacause they don't have an "@" in its memory hash and different zones in memory.

This little code works so fine to me! Now i can finish some great engines that i'm making that work with memory management, weak references and ID based on memory.

I hope this can help you.

Bye, and good luck, my friend!

Jaf answered 27/8, 2009 at 19:21 Comment(4)
Haha, this is certainly a crazy hack!Sideline
Just wanted to say that the top answer here is BROKEN on mobile devices. Basically the returned memory addresses will NOT be unique; as far as I can tell this is due to more efficient memory handling in AIR as opposed to Flash Player. The solution posted by Lakshmi Narayana works across all devices and is faster and more reliable.Marksman
for the regexp part, String( e ).replace( /.*(@\w+).*/, "$1" ) works as wellIntertwine
Another note: this only works for english (the regexp specifies "to"), so to make it work where your errors can come out in multiple languages: String( e ).replace( /.*([@|\$].*?) \S+ .*$/gi, "$1" )Intertwine
N
11

Diney Bomfim's solution worked like a charm. I wrapped this in a class named DebugUtils in a function named 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 { }

Then I could use this function from anywhere and trace it, like so:

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

Thanks so much for this answer!

Norwegian answered 2/12, 2011 at 21:19 Comment(1)
if you remove the function from the class, remove the static, and rename the file getObjectMemoryHash.as, then you'll be able to just use it directly, much like getTimer()Intertwine
C
6

Off the top of my head the only way I can see to pull this off would be to use a Dictionary object (you'd probably want to enable weak keys to avoid any side effects) and then just take the objects as you create them and use them as a key to an incrementing ID counter. Then you could simply look to see if two objects existed as a keys in the Dictionary and if so compare the values stored there.

Catherincatherina answered 27/8, 2009 at 19:54 Comment(1)
ah, yea – that's not a bad idea. Thanks!Dowland
B
5
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;
}

This is working fine installer but it takes unique identification number

Babism answered 2/6, 2012 at 3:50 Comment(0)
M
2

Take a look at Adobe's Scout Debugger - it's a far more powerful debugger

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

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

Mountain answered 17/9, 2013 at 15:58 Comment(0)
L
1

AFAIK there is no way to get to the value that the debugger shows you at runtime.

Total shot in the dark but I think you can use the === comparison to determine if two objects are the same object (in contrast to == that compares the values of the objects). But I could be totally wrong on that.

Logion answered 27/8, 2009 at 20:11 Comment(3)
It's true that '===' will compare the identity of two objects… But that won't help me much here (unless I keep a reference to every object, then…)Dowland
@David: If you don't have a reference to every object than how are you accessing your objects? If you don't have references to your objects, they will be garbage collected.Hebbel
I guess that wasn't clear – there will be references to every instance somewhere, but there won't be "one central repository of all my instances".Dowland

© 2022 - 2024 — McMap. All rights reserved.