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.

Laurel
  • 5,965
  • 14
  • 31
  • 57
David Wolever
  • 148,955
  • 89
  • 346
  • 502
  • 1
    you may wanna have a look at this: http://stackoverflow.com/questions/1151627/object-reference-as-string/1153833#1153833, which quite what branden proposed ... :) – back2dos Aug 30 '09 at 14:04

6 Answers6

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!

Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
Diney Bomfim
  • 1
  • 3
  • 2
  • Haha, this is certainly a crazy hack! – Marcus Stade Dec 30 '10 at 22:10
  • 1
    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. – Dave Fleming Mar 30 '13 at 06:56
  • for the regexp part, `String( e ).replace( /.*(@\w+).*/, "$1" )` works as well – divillysausages Nov 30 '13 at 19:12
  • 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" )` – divillysausages Mar 07 '14 at 10:52
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!

Ellis Elkins
  • 131
  • 1
  • 5
  • 3
    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()` – divillysausages Jan 01 '12 at 14:17
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.

Branden Hall
  • 4,468
  • 18
  • 19
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

Perception
  • 79,279
  • 19
  • 185
  • 195
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

Nick Wood
  • 680
  • 6
  • 10
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.

James Ward
  • 29,283
  • 9
  • 49
  • 85
  • 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…) – David Wolever Aug 27 '09 at 20:15
  • @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. – Luke Aug 28 '09 at 06:12
  • 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". – David Wolever Aug 28 '09 at 15:23