Saltar al contenido

Imprimir una dirección de memoria variable en Swift

Es fundamental entender el código de forma correcta previamente a utilizarlo a tu trabajo y si ttienes algo que aportar puedes compartirlo con nosotros.

Solución:

Nota: Esto es para tipos de referencia.

Rápido 4/5:

print(Unmanaged.passUnretained(someVar).toOpaque())

Imprime la dirección de memoria de someVar. (gracias a @Ying)


Rápido 3.1:

print(Unmanaged.passUnretained(someVar as AnyObject).toOpaque())

Imprime la dirección de memoria de someVar.


rápido 2

Esto ahora es parte de la biblioteca estándar: unsafeAddressOf.

/// Return an UnsafePointer to the storage used for `object`.  There's
/// not much you can do with this other than use it to identify the
/// object

rápido 3

Para Swift 3, use withUnsafePointer:

var str = "A String"
withUnsafePointer(to: &str) 
    print(" str value (str) has address: ($0)")

Tenga en cuenta que esta respuesta era bastante antigua. Muchos de los métodos que describe ya no funcionan. Específicamente .core ya no se puede acceder.

Sin embargo, la respuesta de @drew es correcta y simple:

Esto ahora es parte de la biblioteca estándar: unsafeAddressOf.

Así que la respuesta a tus preguntas es:

println(" str value (str) has address: (unsafeAddressOf(str))")

Aquí está la respuesta original que se marcó como correcta (para posteridad/cortesía):

Swift “oculta” los punteros, pero aún existen bajo el capó. (porque el tiempo de ejecución lo necesita y por razones de compatibilidad con Objc y C)

Sin embargo, hay algunas cosas que debe saber, pero primero, ¿cómo imprimir la dirección de memoria de una cadena Swift?

    var aString : String = "THIS IS A STRING"
    NSLog("%p", aString.core._baseAddress)  // _baseAddress is a COpaquePointer
   // example printed address 0x100006db0

Esto imprime la dirección de memoria del stringsi abre XCode -> Flujo de trabajo de depuración -> Ver memoria y va a la dirección impresa, verá los datos sin procesar del string. Dado que este es un string literal, esta es una dirección de memoria dentro del almacenamiento del binario (no pila o montón).

Sin embargo, si lo haces

    var aString : String = "THIS IS A STRING" + "This is another String"
    NSLog("%p", aString.core._baseAddress)

    // example printed address 0x103f30020

Esto estará en la pila, porque el string se crea en tiempo de ejecución

NOTA: .core._baseAddress no está documentado, lo encontré buscando en el inspector de variables y puede estar oculto en el futuro

_baseAddress no está disponible en todos los tipos, aquí otro ejemplo con un CInt

    var testNumber : CInt = 289
    takesInt(&testNumber)

Donde takesInt es una función auxiliar de C como esta

void takesInt(int *intptr)

    printf("%p", intptr);

En el lado de Swift, esta función es takesInt(intptr: CMutablePointer)por lo que lleva un CMutablePointer a un CInt, y puede obtenerlo con &varname

La función imprime 0x7fff5fbfed98, y en esta dirección de memoria encontrarás 289 (en notación hexadecimal). Puede cambiar su contenido con *intptr = 123456

Ahora, algunas otras cosas que debe saber.

String, en swift, es un tipo primitivo, no un objeto.
CInt es un tipo Swift asignado al tipo C int.
Si desea la dirección de memoria de un objeto, debe hacer algo diferente.
Swift tiene algunos tipos de punteros que se pueden usar al interactuar con C, y puede leer sobre ellos aquí: Tipos de punteros de Swift
Además, puede comprender más sobre ellos explorando su declaración (cmd + clic en el tipo), para comprender cómo convertir un tipo de puntero en otro

    var aString : NSString = "This is a string"  // create an NSString
    var anUnmanaged = Unmanaged.passUnretained(aString)   // take an unmanaged pointer
    var opaque : COpaquePointer = anUnmanaged.toOpaque()   // convert it to a COpaquePointer
    var mut : CMutablePointer = &opaque   // this is a CMutablePointer

    printptr(mut)   // pass the pointer to an helper function written in C

printptr es una función auxiliar de C que creé, con esta implementación

void printptr(void ** ptr)

    printf("%p", *ptr);

Nuevamente, un ejemplo de la dirección impresa: 0x6000000530b0 y si pasa por el inspector de memoria encontrará su NSString

Una cosa que puede hacer con punteros en Swift (esto incluso se puede hacer con parámetros de entrada y salida)

    func playWithPointer (stringa :AutoreleasingUnsafePointer) 
    
        stringa.memory = "String Updated";
    

    var testString : NSString = "test string"
    println(testString)
    playWithPointer(&testString)
    println(testString)

O, interactuando con Objc / c

// objc side
+ (void)writeString:(void **)var

    NSMutableString *aString = [[NSMutableString alloc] initWithFormat:@"pippo %@", @"pluto"];
    *var = (void *)CFBridgingRetain(aString);   // Retain!


// swift side
var opaque = COpaquePointer.null()   // create a new opaque pointer pointing to null
TestClass.writeString(&opaque)
var string = Unmanaged.fromOpaque(opaque).takeRetainedValue()
println(string)
// this prints pippo pluto

Nos encantaría que puedieras mostrar este post si lograste el éxito.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *