2009-08-27 5 views
30

de FlexBuilder le mostrará la "posición de memoria" (o, sólo puedo suponer, algo más o menos análogo) de cualquier instancia dentro del alcance:¿Cómo puedo obtener la "ubicación de memoria" de una instancia en ActionScript? depurador

debugger memory location http://img.skitch.com/20090827-d5nhcnsja3wcgecif3b2dd5ase.png

pero me gustaría obtener esta información en código (algo así como la función id de Python), por lo que podría rastrear fácilmente cómo se mueven los objetos en el sistema. Por ejemplo, podría tener:

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

A continuación, en otro lugar que podría utilizar:

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

Para asegurarse de que ambas partes de código se trata de la misma instancia.

Ahora, sé que muchas clases AS implementan la interfaz IUID ... Pero también hay un montón de clases que no (por ejemplo, matrices y objetos antiguos), así que eso no resolvería mi problema .

Me doy cuenta de que también podría envolver objetos en un ObjectProxy, pero eso sería menos que ideal también.

+1

se Puede echar un vistazo a esto: http://stackoverflow.com/questions/1151627/object-reference-as-string/1153833#1153833, que q uite lo que Branden propuso ... :) – back2dos

+0

¡Ah, se ve bien, gracias! –

Respuesta

59

En verdad le aconsejo que no use esto demasiado ... es muy caro. Adobe necesita crear una función nativa para devolvernos esto.

Pero, por ahora ... intente esto:

Usted tendrá que hacer una coerción explícita para conseguirlo! Porque cuando se hace explícita y la coacción se obtiene un error como este:

 
TypeError: Error #1034: 
Type Coercion failed: cannot convert [email protected] to flash.utils.ByteArray. 

Nótese que en este error se obtiene lo que quiere ... el @ 1c49d31. Este hash es como una identificación en la asignación de memoria.

Hice un montón de pruebas. Este hash simplemente cambia cuando se llama "nuevo" (en C idiomas es equivalente a [[... alloc] init]) y para funciones estáticas y propiedades estáticas, la asignación ocurre un poco diferente ... de todos modos ...

Respaldo a Flash, el problema es que no tenemos una manera directa de obtener este hash sin un error.

Pero este no es un gran problema. Todo lo que necesitas es utilizar un poco de "tratar" y "captura" De esta manera:

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

y listo! ¡Obtendrá el hash sin resultado en un error! Después de esto lo hice de una manera más refinated ... Prueba esto:

var memoryHash:String; 

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

internal final class FakeClass { } 

Un poco de explicar esto: El fakeClass es estar seguro de esto generará un error. RegularExpression captura los últimos @ ... que aparecen. Porque los Objetos y las Funciones generan diferentes mensajes en este Error. Y el $ es para atrapar los objetos estáticos, la clase y las funciones, ya que no tienen una "@" en su memoria hash y diferentes zonas en la memoria.

¡Este pequeño código funciona tan bien para mí! Ahora puedo terminar algunos grandes motores que estoy haciendo que funcionen con la administración de memoria, las referencias débiles y la identificación basada en la memoria.

Espero que esto pueda ayudarlo.

¡Adiós, y buena suerte, amigo!

+0

hahahha Diney, eso es brillante. Buen trabajo. –

+0

¡Jaja, esto es ciertamente un hack loco! –

+0

felicitaciones que es increíble! –

6

Por fuera de mi cabeza, la única forma en que puedo ver para lograr esto sería usar un objeto de diccionario (probablemente querría habilitar teclas débiles para evitar efectos secundarios) y luego simplemente tomar los objetos como los creas y los utilizas como una clave para incrementar el contador de ID. Entonces, simplemente podría ver si existen dos objetos como claves en el Diccionario y, de ser así, comparar los valores almacenados allí.

+0

ah, sí, eso no es una mala idea. ¡Gracias! –

1

AFAIK no hay forma de llegar al valor que el depurador muestra en el tiempo de ejecución.

Disparo total en la oscuridad, pero creo que puede usar la comparación === para determinar si dos objetos son el mismo objeto (en contraste con == que compara los valores de los objetos). Pero podría estar totalmente equivocado en eso.

+0

Es cierto que '===' comparará la identidad de dos objetos ... Pero eso no me ayudará mucho aquí (a menos que guarde una referencia a cada objeto, entonces ...) –

+0

@David: Si no tiene una referencia a cada objeto que no sea cómo estás accediendo a tus objetos? Si no tiene referencias a sus objetos, serán basura recolectada. – Luke

+0

Supongo que no estaba claro: habrá referencias a cada instancia * en algún lugar *, pero no habrá "un repositorio central de todas mis instancias". –

11

La solución de Diney Bomfim funcionó a las mil maravillas. Envolví esto en una clase llamada DebugUtils en una función llamada 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 { } 

Entonces podría utilizar esta función desde cualquier lugar y rastrear, así:

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

Muchas gracias por esta respuesta!

+3

si elimina la función de la clase, elimina la estática y cambia el nombre del archivo getObjectMemoryHash.as, entonces podrá usarlo directamente, al igual que' getTimer() ' – divillysausages

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; 
} 

esto está funcionando bien instalador pero se necesita el número de identificación único

Cuestiones relacionadas