Apakah ada cara untuk mensimulasikan [NSString stringWithFormat:@"%p", myVar]
, dari Objective-C, dalam bahasa Swift yang baru?
Sebagai contoh:
let str = "A String"
println(" str value \(str) has address: ?")
swift
debugging
memory-address
apouche
sumber
sumber
[NSString stringWithFormat:@"%p", myVar]
,myVar
harus berupa pointer. Dalam kode Swift Anda,str
bukan penunjuk. Jadi perbandingannya tidak berlaku.Jawaban:
Cepat 2
Ini sekarang merupakan bagian dari perpustakaan standar:
unsafeAddressOf
.Cepat 3
Untuk Swift 3, gunakan
withUnsafePointer
:sumber
withUnsafePointer
mengakibatkancannot pass immutable value as inout argument
kesalahan.print(self.description)
cetak<MyViewController: 0x101c1d580>
, kami menggunakannya sebagai referensi.var mutableSelf = self; withUnsafePointer(to: &mutableSelf) { print(String(format: "%p", $0)) }
cetakan0x16fde4028
yang alamatnya jelas berbeda. Adakah yang bisa menjelaskan mengapa?0x101c1d580
seperti yang diharapkan:print(String(format: "%p", unsafeBitCast(self, to: Int.self)))
UnsafePointer
adalah sebuah struct, jadi untuk mencetak alamat yang ditunjuknya (dan bukan struct itu sendiri) Anda harus mencetakString(format: "%p", $0.pointee)
!Catatan: Ini untuk jenis referensi.
Swift 4/5:
Mencetak alamat memori someVar. (terima kasih kepada @Ying)
Swift 3.1:
Mencetak alamat memori someVar.
sumber
print(Unmanaged<AnyObject>.passUnretained(someVar as AnyObject).toOpaque())
Unmanaged
itu dapat dilakukan seperti ini:print(Unmanaged<AnyObject>.fromOpaque(&myStruct).toOpaque())
.Unmanaged.passUnretained(someVar).toOpaque()
(tidak perlu spesifikasi umum)debugDescription
untuk menambahkannya .Perhatikan bahwa jawaban ini sudah cukup lama. Banyak metode yang dijelaskannya tidak lagi berfungsi. Khususnya
.core
tidak dapat diakses lagi.Namun, jawaban @ drew benar dan sederhana:
Jadi jawaban untuk pertanyaan Anda adalah:
Inilah jawaban asli yang ditandai benar (untuk keturunan / kesopanan):
Swift "menyembunyikan" pointer, tetapi mereka masih ada di bawah tenda. (karena runtime membutuhkannya, dan untuk alasan kompatibilitas dengan Objc dan C)
Ada beberapa hal yang perlu diketahui, tetapi pertama-tama bagaimana cara mencetak alamat memori dari Swift String?
Ini mencetak alamat memori dari string, jika Anda membuka XCode -> Debug Workflow -> View Memory dan pergi ke alamat yang dicetak, Anda akan melihat data mentah dari string. Karena ini adalah string literal, ini adalah alamat memori di dalam penyimpanan biner (bukan stack atau heap).
Namun, jika Anda melakukannya
Ini akan berada di tumpukan, karena string dibuat saat runtime
CATATAN: .core._baseAddress tidak didokumentasikan, saya menemukannya mencari di variabel inspector, dan mungkin disembunyikan di masa depan
_baseAddress tidak tersedia di semua jenis, di sini contoh lain dengan CInt
Di mana
takesInt
fungsi pembantu C seperti iniDi sisi Swift, fungsi ini adalah
takesInt(intptr: CMutablePointer<CInt>)
, jadi dibutuhkan CMutablePointer ke CInt, dan Anda bisa mendapatkannya dengan & varnameFungsi mencetak
0x7fff5fbfed98
, pada alamat memori ini Anda akan menemukan 289 (dalam notasi heksadesimal). Anda dapat mengubah kontennya dengan*intptr = 123456
Sekarang, beberapa hal lain yang perlu diketahui.
String, dengan cepat, adalah tipe primitif, bukan objek.
CInt adalah tipe Swift yang dipetakan ke Tipe C int.
Jika Anda ingin alamat memori suatu objek, Anda harus melakukan sesuatu yang berbeda.
Swift memiliki beberapa Tipe Pointer yang dapat digunakan saat berinteraksi dengan C, dan Anda dapat membacanya di sini: Tipe Swift Pointer
Selain itu, Anda dapat memahami lebih lanjut tentang mereka yang mengeksplorasi deklarasi mereka (cmd + klik pada jenisnya), untuk memahami cara mengonversi jenis pointer ke yang lain
printptr
adalah fungsi pembantu C yang saya buat, dengan implementasi iniSekali lagi, contoh alamat dicetak:,
0x6000000530b0
dan jika Anda pergi melalui inspektur memori Anda akan menemukan NSString AndaSatu hal yang dapat Anda lakukan dengan pointer di Swift (ini bahkan dapat dilakukan dengan parameter inout)
Atau, berinteraksi dengan Objc / c
sumber
Untuk mendapatkan alamat (tumpukan) dari suatu objek
( Sunting: Swift 1.2 sekarang termasuk fungsi serupa yang disebut
unsafeAddressOf
.)Dalam Objective-C ini akan menjadi
[NSString stringWithFormat:@"%p", o]
.o
adalah referensi ke instance. Jadi, jikao
ditugaskan ke variabel laino2
, alamat yang dikembalikan untuko2
akan sama.Ini tidak berlaku untuk struct (termasuk
String
) dan tipe primitif (sepertiInt
), karena mereka tinggal langsung di stack. Tetapi kita dapat mengambil lokasi di stack.Untuk mendapatkan (tumpukan) alamat struct, tipe bawaan atau referensi objek
Dalam Objective-C ini akan menjadi
[NSString stringWithFormat:@"%p", &o]
atau[NSString stringWithFormat:@"%p", &i]
.s
adalah struct. Jadi jikas
ditugaskan ke variabel lains2
, nilainya akan disalin dan alamat yang dikembalikans2
akan berbeda.Bagaimana itu cocok bersama (pointer rekap)
Seperti di Objective-C, ada dua alamat berbeda yang terkait dengannya
o
. Yang pertama adalah lokasi objek, yang kedua adalah lokasi referensi (atau pointer) ke objek.Ya, ini berarti bahwa isi alamat 0x7fff5fbfe658 adalah angka 0x610000001111 seperti yang dapat dikatakan oleh debugger kepada kami:
Jadi, kecuali untuk string yang menjadi struct, secara internal semua ini cukup banyak bekerja sama dengan di (Objective-) C.
(Lancar pada Xcode 6.3)
sumber
TL; DR
( Intisari )
Di Swift kami berurusan dengan tipe nilai (struktur) atau tipe referensi (kelas). Ketika melakukan:
Beberapa memori dialokasikan pada alamat X, dan pada alamat ini kita akan menemukan nilai 42. Melakukan
&n
membuat pointer menunjuk ke alamat X, oleh karena itu&n
memberitahu kita di manan
berada.Ketika melakukan:
Memori dialokasikan di dua tempat:
Seperti yang dikatakan, kelas adalah tipe referensi: jadi nilai
c
terletak di alamat X, di mana kita akan menemukan nilai Y. Dan di alamat Y + 16 kita akan menemukanfoo
dan di alamat Y + 24 kita akan menemukanbar
( pada + 0 dan + 8 kita akan menemukan tipe data dan jumlah referensi, saya tidak bisa memberi tahu Anda lebih banyak tentang ini ...).0x2a
adalah 42 (foo) dan0x54
84 (bar).Dalam kedua kasus, menggunakan
&n
atau&c
akan memberi kami alamat X. Untuk tipe nilai, itulah yang kami inginkan, tetapi bukan untuk tipe referensi.Ketika melakukan:
Kami membuat pointer pada referensi, yaitu pointer yang menunjuk ke alamat X. Hal yang sama saat menggunakan
withUnsafePointer(&c) {}
.Sekarang kita memiliki pemahaman yang lebih baik tentang apa yang terjadi di bawah tenda, dan bahwa kita sekarang bahwa pada alamat X kita akan menemukan alamat Y (yang mana kita inginkan) kita dapat melakukan hal berikut untuk mendapatkannya:
Memverifikasi:
Ada cara lain untuk melakukan ini:
toOpaque()
sebenarnya meneleponunsafeBitCast(c, to: UnsafeMutableRawPointer.self)
.Saya harap ini membantu ... itu berhasil untuk saya 😆.
sumber
MemoryLocation
menghasilkan 2 alamat yang berbeda.Jenis referensi:
===
operator identitas digunakan untuk memeriksa 2 objek yang menunjuk ke referensi yang sama.ObjectIdentifier
untuk mendapatkan alamat memoriKode:
Jenis nilai:
sumber
Gunakan ini saja:
sumber
MyClass?
" tidak sesuai dengan CVarArg, Anda bisa melakukannyaextension Optional : CVarArg { }
. Kalau tidak, ini sepertinya mencetak alamat tanpa semua kegilaan "tidak aman" dari jawaban lain.var _cVarArgEncoding: [Int]
onCVarArg
. Tidak jelas bagaimana itu harus dilaksanakan.Jika Anda hanya ingin melihat ini di debugger dan tidak melakukan hal lain dengan itu, tidak perlu benar-benar mendapatkan
Int
pointer. Untuk mendapatkan representasi string dari alamat objek dalam memori, cukup gunakan sesuatu seperti ini:Contoh penggunaan:
Selain itu, ingatlah bahwa Anda cukup mencetak objek tanpa mengesampingkannya
description
, dan itu akan menunjukkan alamat penunjuknya di samping teks yang lebih deskriptif (jika sering samar).sumber
Cepat 5
Pemakaian:
sumber
Unmanaged.passUnretained(myObject).toOpaque()
bekerja dengan baik sebagai gantinya.AnyObject
parameter. Saya lebih sukaAny
sebagai tipe input.Di Swift4 tentang Array:
sumber
self?.array
.Jawaban lain baik-baik saja, meskipun saya sedang mencari cara untuk mendapatkan alamat pointer sebagai integer:
Sedikit tindak lanjut.
sumber
Jawaban @Drew menyediakan hanya dapat digunakan untuk tipe kelas.
Jawaban @nschum hanya bisa untuk tipe struct.
Namun jika Anda menggunakan metode kedua untuk mendapatkan alamat array dengan elemen tipe nilai. Swift akan menyalin seluruh array karena dalam Swift array adalah copy-on-write dan Swift tidak dapat memastikannya berperilaku seperti ini setelah melewati kontrol ke C / C ++ (Yang dipicu dengan menggunakan
&
untuk mendapatkan alamat). Dan jika Anda menggunakan metode pertama sebagai gantinya, itu akan secara otomatis dikonversiArray
keNSArray
yang pasti sesuatu yang tidak kita inginkan.Jadi cara paling sederhana dan terpadu yang saya temukan adalah menggunakan instruksi lldb
frame variable -L yourVariableName
.Atau Anda dapat menggabungkan jawaban mereka:
sumber
Ini untuk Swift 3.
Seperti @CharlieMonroe saya ingin mendapatkan alamat sebagai integer. Secara khusus, saya ingin alamat objek Thread untuk digunakan sebagai ID utas dalam modul logging diagnostik, untuk situasi di mana tidak ada nama utas yang tersedia.
Berdasarkan kode Charlie Monroe, inilah yang saya buat sejauh ini. Tetapi waspadalah, saya sangat baru di Swift, ini mungkin tidak benar ...
Pernyataan terakhir ada karena tanpa itu saya mendapatkan alamat seperti 0x60000007DB3F. Operasi modulo dalam pernyataan terakhir mengubahnya menjadi 0x7DB3F.
sumber
Solusi saya di Swift 3
kode ini membuat deskripsi seperti deskripsi default
<MyClass: 0x610000223340>
sumber
Ini tentu bukan cara tercepat atau teraman untuk melakukannya. Tapi hal ini bekerja untukku. Ini akan memungkinkan subclass nsobject untuk mengadopsi properti ini.
sumber