Est-il possible de simuler le [NSString stringWithFormat:@"%p", myVar]
, à partir d'Objective-C, dans le nouveau langage Swift?
Par exemple:
let str = "A String"
println(" str value \(str) has address: ?")
swift
debugging
memory-address
apouche
la source
la source
[NSString stringWithFormat:@"%p", myVar]
,myVar
doit être un pointeur. Dans votre code Swift, cestr
n'est pas un pointeur. La comparaison ne s'applique donc pas.Réponses:
Swift 2
Ce fait maintenant partie de la bibliothèque standard:
unsafeAddressOf
.Swift 3
Pour Swift 3, utilisez
withUnsafePointer
:la source
withUnsafePointer
entraîne unecannot pass immutable value as inout argument
erreur.print(self.description)
impressions<MyViewController: 0x101c1d580>
, nous l'utilisons comme référence.var mutableSelf = self; withUnsafePointer(to: &mutableSelf) { print(String(format: "%p", $0)) }
imprime0x16fde4028
qui est une adresse clairement différente. Quelqu'un peut-il expliquer pourquoi?0x101c1d580
comme prévu:print(String(format: "%p", unsafeBitCast(self, to: Int.self)))
UnsafePointer
est une structure, donc pour imprimer l'adresse vers laquelle elle pointe (et non la structure elle-même), vous devez imprimerString(format: "%p", $0.pointee)
!Remarque: Ceci est pour les types de référence.
Swift 4/5:
Imprime l'adresse mémoire de someVar. (merci à @Ying)
Swift 3.1:
Imprime l'adresse mémoire de someVar.
la source
print(Unmanaged<AnyObject>.passUnretained(someVar as AnyObject).toOpaque())
Unmanaged
cela peut être fait comme ceci:print(Unmanaged<AnyObject>.fromOpaque(&myStruct).toOpaque())
.Unmanaged.passUnretained(someVar).toOpaque()
(pas besoin de spécification générique)debugDescription
à la fin de celle-ci.Notez que cette réponse était assez ancienne. Bon nombre des méthodes qu'il décrit ne fonctionnent plus. Plus précisément,
.core
il n'est plus accessible.Cependant, la réponse de @ drew est correcte et simple:
La réponse à vos questions est donc:
Voici la réponse originale qui a été marquée correcte (pour la postérité / politesse):
Swift "cache" les pointeurs, mais ils existent toujours sous le capot. (parce que le runtime en a besoin, et pour des raisons de compatibilité avec Objc et C)
Il y a peu de choses à savoir cependant, mais d'abord comment imprimer l'adresse mémoire d'une Swift String?
Cela imprime l'adresse mémoire de la chaîne, si vous ouvrez XCode -> Debug Workflow -> Afficher la mémoire et allez à l'adresse imprimée, vous verrez les données brutes de la chaîne. Puisqu'il s'agit d'un littéral de chaîne, il s'agit d'une adresse mémoire à l'intérieur du stockage du binaire (pas de pile ou de tas).
Cependant, si vous faites
Ce sera sur la pile, car la chaîne est créée au moment de l'exécution
REMARQUE: .core._baseAddress n'est pas documenté, je l'ai trouvé à la recherche dans l'inspecteur de variables, et il peut être caché à l'avenir
_baseAddress n'est pas disponible sur tous les types, voici un autre exemple avec un CInt
Où
takesInt
est une fonction d'assistance C comme celle-ciDu côté Swift, cette fonction est
takesInt(intptr: CMutablePointer<CInt>)
, donc elle prend un CMutablePointer vers un CInt, et vous pouvez l'obtenir avec & varnameLa fonction imprime
0x7fff5fbfed98
, à cette adresse mémoire, vous trouverez 289 (en notation hexadécimale). Vous pouvez modifier son contenu avec*intptr = 123456
Maintenant, quelques autres choses à savoir.
La chaîne, en swift, est un type primitif, pas un objet.
CInt est un type Swift mappé sur le type C int.
Si vous voulez l'adresse mémoire d'un objet, vous devez faire quelque chose de différent.
Swift a quelques types de pointeurs qui peuvent être utilisés lors de l'interaction avec C, et vous pouvez en savoir plus ici: Types de pointeurs Swift
De plus, vous pouvez en savoir plus sur eux en explorant leur déclaration (cmd + cliquez sur le type), pour comprendre comment convertir un type de pointeur vers un autre
printptr
est une fonction d'assistance C que j'ai créée, avec cette implémentationEncore une fois, un exemple d'adresse imprimée:,
0x6000000530b0
et si vous passez par l'inspecteur de mémoire, vous trouverez votre NSStringUne chose que vous pouvez faire avec des pointeurs dans Swift (cela peut même être fait avec des paramètres inout)
Ou, interagir avec Objc / c
la source
Pour obtenir l'adresse (de tas) d'un objet
( Edit: Swift 1.2 inclut désormais une fonction similaire appelée
unsafeAddressOf
.)En Objective-C, ce serait
[NSString stringWithFormat:@"%p", o]
.o
est une référence à l'instance. Donc, sio
est affecté à une autre variableo2
, l'adresse renvoyée pouro2
sera la même.Cela ne s'applique pas aux structures (y compris
String
) et aux types primitifs (commeInt
), car ceux-ci vivent directement sur la pile. Mais nous pouvons récupérer l'emplacement sur la pile.Pour obtenir l'adresse (de pile) d'une structure, d'un type intégré ou d'une référence d'objet
En Objective-C, ce serait
[NSString stringWithFormat:@"%p", &o]
ou[NSString stringWithFormat:@"%p", &i]
.s
est struct. Donc, sis
est affecté à une autre variables2
, la valeur sera copiée et l'adresse renvoyée pours2
sera différente.Comment ça s'emboîte (récapitulatif du pointeur)
Comme dans Objective-C, deux adresses différentes sont associées à
o
. Le premier est l'emplacement de l'objet, le second est l'emplacement de la référence (ou du pointeur) vers l'objet.Oui, cela signifie que le contenu de l'adresse 0x7fff5fbfe658 est le numéro 0x6100000011d0 comme le débogueur peut nous le dire:
Donc, à l'exception des chaînes qui sont des structures, en interne, tout fonctionne à peu près de la même manière que dans (Objective-) C.
(À jour à partir de Xcode 6.3)
la source
TL; DR
( Gist )
Dans Swift, nous traitons soit des types valeur (structures), soit des types référence (classes). En faisant:
Une partie de la mémoire est allouée à l'adresse X, et à cette adresse nous trouverons la valeur 42. Faire
&n
crée un pointeur pointant vers l'adresse X, donc&n
nous indique oùn
se trouve.En faisant:
La mémoire est allouée à deux endroits:
Comme dit, les classes sont des types de référence: donc la valeur de
c
est située à l'adresse X, à laquelle nous trouverons la valeur de Y. Et à l'adresse Y + 16 nous trouveronsfoo
et à l'adresse Y + 24 nous trouveronsbar
( à + 0 et + 8, nous trouverons des données de type et des nombres de références, je ne peux pas vous en dire beaucoup plus à ce sujet ...).0x2a
vaut 42 (foo) et0x54
84 (bar).Dans les deux cas, utiliser
&n
ou&c
nous donnera l'adresse X. Pour les types valeur, c'est ce que nous voulons, mais pas pour les types référence.En faisant:
Nous créons un pointeur sur la référence, c'est-à-dire un pointeur qui pointe vers l'adresse X. Même chose lors de l'utilisation
withUnsafePointer(&c) {}
.Maintenant que nous avons une meilleure compréhension de ce qui se passe sous le capot, et que nous maintenant qu'à l'adresse X nous trouverons l'adresse Y (qui est celle que nous voulons), nous pouvons faire ce qui suit pour l'obtenir:
Vérification:
Il existe d'autres moyens de procéder:
toOpaque()
appelle réellementunsafeBitCast(c, to: UnsafeMutableRawPointer.self)
.J'espère que cela a aidé ... cela m'a aidé 😆.
la source
MemoryLocation
produit 2 adresses différentes.Types de référence:
===
L'opérateur d'identité est utilisé pour vérifier que 2 objets pointent vers la même référence.ObjectIdentifier
pour obtenir l'adresse mémoireCode:
Types de valeur:
la source
Utilisez simplement ceci:
la source
MyClass?
" n'est pas conforme à CVarArg, vous pouvez le faireextension Optional : CVarArg { }
. Sinon, cela semble imprimer des adresses sans toute la folie «non sûre» des autres réponses.var _cVarArgEncoding: [Int]
onCVarArg
. Pas clair comment cela devrait être mis en œuvre.Si vous voulez juste voir cela dans le débogueur et ne rien faire d'autre avec lui, il n'est pas nécessaire d'obtenir le
Int
pointeur. Pour obtenir la représentation sous forme de chaîne de l'adresse d'un objet en mémoire, utilisez simplement quelque chose comme ceci:Exemple d'utilisation:
De plus, rappelez- vous que vous pouvez simplement imprimer un objet sans le remplacer
description
, et il affichera son adresse de pointeur à côté d'un texte plus descriptif (si souvent cryptique).la source
Swift 5
Usage:
la source
Unmanaged.passUnretained(myObject).toOpaque()
fonctionne correctement à la place.AnyObject
paramètre. Je préféreraisAny
comme type d'entrée.Dans Swift4 à propos de Array:
la source
self?.array
.Les autres réponses sont correctes, même si je cherchais un moyen d'obtenir l'adresse du pointeur sous forme d'entier:
Juste un petit suivi.
la source
La réponse fournie par @Drew ne peut être utilisée que pour le type de classe.
La réponse fournie par @nschum ne peut être que pour le type struct.
Cependant, si vous utilisez la deuxième méthode pour obtenir l'adresse d'un tableau avec un élément de type valeur. Swift copiera tout le tableau car dans Swift, le tableau est une copie sur écriture et Swift ne peut pas s'assurer qu'il se comporte de cette façon une fois qu'il passe le contrôle à C / C ++ (qui est déclenché en utilisant
&
pour obtenir l'adresse). Et si vous utilisez la première méthode à la place, elle sera automatiquement convertieArray
enNSArray
ce que nous ne voulons sûrement pas.Donc, le moyen le plus simple et le plus unifié que j'ai trouvé est d'utiliser l'instruction lldb
frame variable -L yourVariableName
.Ou vous pouvez combiner leurs réponses:
la source
Ceci est pour Swift 3.
Comme @CharlieMonroe, je voulais obtenir l'adresse sous forme d'entier. Plus précisément, je voulais que l'adresse d'un objet Thread soit utilisée comme ID de thread dans un module de journalisation de diagnostic, pour les situations où aucun nom de thread n'était disponible.
Basé sur le code de Charlie Monroe, voici ce que j'ai trouvé jusqu'ici. Mais attention, je suis très nouveau sur Swift, ce n'est peut-être pas correct ...
La dernière déclaration est là parce que sans elle, j'obtenais des adresses comme 0x60000007DB3F. L'opération modulo dans la dernière instruction convertit cela en 0x7DB3F.
la source
Ma solution sur Swift 3
ce code crée une description comme la description par défaut
<MyClass: 0x610000223340>
la source
Ce n'est certainement pas le moyen le plus rapide ou le plus sûr de s'y prendre. Mais cela fonctionne pour moi. Cela permettra à toute sous-classe nsobject d'adopter cette propriété.
la source