2009-08-27 13 views
30

di FlexBuilder vi mostrerà la "posizione di memoria" (o, posso solo supporre, qualcosa di grosso modo analogo) di qualsiasi istanza in-campo di applicazione:Come posso ottenere la "posizione di memoria" di un'istanza in ActionScript? debugger

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

ma mi piacerebbe per ottenere queste informazioni in codice (una specie di funzione di Python id), così ho potuto facilmente tracciare come gli oggetti si muovono attraverso il sistema. Per esempio, potrei avere:

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

Poi qualche altra parte ho potuto utilizzare:

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

Per assicurarsi entrambi i bit di codice che fare con la stessa istanza.

Ora, so che molte classi AS implementano l'interfaccia IUID ... Ma ci sono anche un sacco di classi che non lo fanno (semplici vecchi array e oggetti, ad esempio), in modo da non risolvere il mio problema .

Mi rendo conto che potrei anche avvolgere gli oggetti in un ObjectProxy, ma anche quello non sarebbe l'ideale.

+1

voi potrebbe volere dare un'occhiata a questo: http://stackoverflow.com/questions/1151627/object-reference-as-string/1153833#1153833, che q uite che marca ha proposto ... :) – back2dos

+0

Ah, sembra buono - grazie! –

risposta

59

In realtà vi consiglio di non usarlo troppo ... è molto costoso. Adobe ha bisogno di creare una funzione nativa per restituirci questo.

Ma, per ora ... provate questo:

Sarà necessario causare un coercizione esplicita per farlo! Perché quando si fanno e coercizione esplicita si ottiene un errore come questo:

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

Si noti che in questo errore si ottiene ciò che si vuole ... l'@ 1c49d31. Questo hash è come un ID nell'allocazione di memoria.

Ho fatto un sacco di test. Questo hash cambia solo quando chiami un "nuovo" (nei linguaggi C equivale a [[allocazione] init]) e per le funzioni statiche e le proprietà statiche, l'allocazione avviene in modo leggermente diverso ... comunque ...

Il backup su Flash, il problema è che non abbiamo un modo diretto per ottenere questo hash senza un errore.

Ma questo non è un grosso problema. Tutto quello che serve è quello di usare un po 'di "prova" e "catturare" Ti piace questa:

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

E voilà! Otterrai l'hash senza risultato in un errore! Dopo questo ho fatto un modo più refinated ... Prova questo:

var memoryHash:String; 

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

internal final class FakeClass { } 

Un po 'di spiegare su questo: La fakeClass è quello di essere sicuro di questo genererà un errore. L'espressione Regular è per catturare l'ultimo @ ... che appare. Poiché gli oggetti e le funzioni generano messaggi diversi su questo errore. E il $ è di catturare gli oggetti statici, la classe e le funzioni, perché non hanno un "@" nel suo hash della memoria e diverse zone in memoria.

Questo piccolo codice funziona così bene per me! Ora posso finire alcuni grandi motori che sto facendo funzionare con gestione della memoria, riferimenti deboli e ID basati sulla memoria.

Spero che questo possa aiutarti.

Ciao, e buona fortuna, amico mio!

+0

hahahha Diney, è geniale. Buon lavoro. –

+0

Haha, questo è certamente un pazzo hack! –

+0

complimenti che è fantastico! –

6

Nella parte superiore della mia testa l'unico modo che posso vedere per rimuoverlo sarebbe utilizzare un oggetto Dizionario (probabilmente si vorranno abilitare i tasti deboli per evitare effetti collaterali) e quindi basta prendere gli oggetti come li crei e li usi come chiave per un contatore ID incrementale. Quindi si potrebbe semplicemente cercare di vedere se due oggetti esistessero come chiavi nel dizionario e in tal caso confrontare i valori memorizzati lì.

+0

ah, sì - non è una cattiva idea. Grazie! –

1

AFAIK non è possibile accedere al valore visualizzato dal debugger in fase di esecuzione.

Tiro totale al buio, ma penso che sia possibile utilizzare il confronto === per determinare se due oggetti sono lo stesso oggetto (a differenza di == che confronta i valori degli oggetti). Ma potrei sbagliarmi completamente su questo.

+0

È vero che '===' confronterà l'identità di due oggetti ... Ma questo non mi aiuterà molto qui (a meno che non tenga un riferimento a ogni oggetto, quindi ...) –

+0

@David: Se non hai un riferimento a ogni oggetto rispetto a come stai accedendo ai tuoi oggetti? Se non si dispone di riferimenti ai propri oggetti, questi verranno raccolti automaticamente. – Luke

+0

Immagino che non fosse chiaro - ci saranno riferimenti a ogni istanza * da qualche parte *, ma non ci sarà "un archivio centrale di tutte le mie istanze". –

11

La soluzione di Diney Bomfim ha funzionato come un fascino. L'ho avvolto in una classe denominata DebugUtils in una funzione denominata 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 { } 

Poi ho potuto utilizzare questa funzione da qualsiasi luogo e rintracciarlo, in questo modo:

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

Grazie mille per questa risposta!

+3

se rimuovi la funzione dalla classe, rimuovi la statica e rinomina il file getObjectMemoryHash.as, allora sarai in grado di usarla direttamente, proprio come' 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; 
} 

Questo è il lavoro di installazione bene, ma ci vuole numero di identificazione univoco