Swift Academy · Pelajaran

Penuding Penimbal Tidak Selamat

Proses memori bersebelahan dengan cekap.

Pelajaran 3 daripada 413 langkah

Penuding Penimbal Tidak Selamat ialah pelajaran Swift Academy percuma di CoddyKit. Ini ialah pelajaran 3 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Swift Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Swift Academy merangkumi sejumlah 4 pelajaran.

Apakah Itu Penuding Buffer

Satu penuding bertip menunjuk kepada satu elemen pada satu-satu masa. UnsafeBufferPointer<T> membalut penuding permulaan serta kiraan, lalu memberikan paparan terhad ke atas blok memori bersebelahan yang mematuhi Collection.

Ini bermakna Anda boleh melakukan iterasi, menggunakan subskrip, pemetaan dan reduce — semua API koleksi yang biasa digunakan pada memori mentah.

// A buffer pointer = base address + element count
// UnsafeBufferPointer<Int>(start: ptr, count: 5)

Buffer Baca Sahaja berbanding Buffer Boleh Ubah

Seperti penuding tunggal, buffer hadir dalam dua bentuk: UnsafeBufferPointer<T> untuk iterasi baca sahaja dan UnsafeMutableBufferPointer<T> apabila Anda juga perlu menetapkan elemen.

let p = UnsafeMutablePointer<Int>.allocate(capacity: 4)
p.initialize(repeating: 0, count: 4)
let buf = UnsafeMutableBufferPointer(start: p, count: 4)
buf[0] = 11
print(buf[0]) // 11

Melakukan Iterasi Seperti Koleksi

Oleh sebab penuding buffer ialah Collection, gelung for mengunjungi setiap elemen mengikut turutan. Tiada pengiraan indeks manual dan tiada risiko tersasar satu pada gelung itu sendiri — walaupun sempadan yang Anda berikan masih menjadi tanggungjawab Anda.

let buf = UnsafeMutableBufferPointer<Int>.allocate(capacity: 3)
_ = buf.initialize(from: [10, 20, 30])
for value in buf { print(value) } // 10, 20, 30

Algoritma Koleksi Tanpa Kos Tambahan

Kesemua map, filter, reduce, enumerated dan indices berfungsi pada penuding buffer. Ini membolehkan Anda memproses memori mentah dengan kod peringkat tinggi sambil mengelakkan peruntukan memori.

let buf = UnsafeMutableBufferPointer<Int>.allocate(capacity: 4)
_ = buf.initialize(from: [1, 2, 3, 4])
let total = buf.reduce(0, +)   // 10
let evens = buf.filter { $0 % 2 == 0 } // [2, 4]
print(total, evens)

Memperuntukkan Buffer Boleh Ubah

UnsafeMutableBufferPointer<T>.allocate(capacity:) menyimpan ruang untuk blok dan mengembalikan buffer dalam satu langkah. Anda masih mesti initialize sebelum membaca dan deallocate apabila selesai.

let buf = UnsafeMutableBufferPointer<Int>.allocate(capacity: 5)
buf.initialize(repeating: 0)
defer {
    buf.deinitialize()
    buf.deallocate()
}

Sempadan Tidak Disemak pada Penghujung

Menggunakan subskrip dalam 0..<count adalah selamat. Namun, buffer tidak dapat mengetahui sama ada kiraan yang Anda berikan adalah betul. Jika Anda membina buffer dengan kiraan yang lebih besar daripada peruntukan sebenar, bacaan akan melepasi hujung ke dalam memori yang tidak ditakrif.

Sentiasa tentukan kiraan daripada peruntukan yang sama dengan yang Anda cipta.

let p = UnsafeMutablePointer<Int>.allocate(capacity: 3)
p.initialize(repeating: 0, count: 3)
// CORRECT: count matches capacity
let good = UnsafeBufferPointer(start: p, count: 3)
// WRONG: count: 10 would read past the block
print(good.count)

Buffer Kosong

Buffer dengan count: 0 adalah sah dan mungkin mempunyai alamat asas nil. Sentiasa semak isEmpty atau biarkan gelung tidak dijalankan, bukannya menyahbungkus baseAddress secara paksa.

let empty = UnsafeBufferPointer<Int>(start: nil, count: 0)
print(empty.isEmpty)       // true
print(empty.count)         // 0
for _ in empty { print("never runs") }

withUnsafeBufferPointer pada Tatasusunan

Cara paling selamat untuk mendapatkan buffer adalah daripada Array sedia ada melalui withUnsafeBufferPointer. Swift menjamin bahawa storan itu bersebelahan dan sah sepanjang tempoh penutupan, jadi Anda tidak perlu melakukan peruntukan manual.

let numbers = [4, 8, 15, 16, 23]
let maxValue = numbers.withUnsafeBufferPointer { buf -> Int in
    var m = buf[0]
    for v in buf where v > m { m = v }
    return m
}
print(maxValue) // 23

Mengubah Storan Tatasusunan

withUnsafeMutableBufferPointer membolehkan Anda menulis terus ke dalam storan tatasusunan. Ini kadangkala digunakan untuk transformasi di tempat yang kritikal dari segi prestasi, apabila ARC dan semakan sempadan akan menambah kos tambahan.

var data = [1, 2, 3, 4]
data.withUnsafeMutableBufferPointer { buf in
    for i in buf.indices { buf[i] *= 10 }
}
print(data) // [10, 20, 30, 40]

baseAddress untuk API C

Apabila memanggil fungsi C yang menjangkakan penuding serta panjang, berikan buffer.baseAddress dan buffer.count. Alamat asas ialah nil hanya untuk buffer kosong, jadi kendalikan keadaan itu.

let bytes: [UInt8] = [0xDE, 0xAD, 0xBE, 0xEF]
bytes.withUnsafeBufferPointer { buf in
    if let base = buf.baseAddress {
        // c_function(base, buf.count)
        print("start:", base, "len:", buf.count)
    }
}

Bila Perlu Menggunakan Penuding Buffer

Gunakan penuding buffer apabila Anda memerlukan akses yang bersebelahan, selamat dari segi jenis dan bergaya koleksi kepada suatu rantau memori: menjambatani tatasusunan C, menghuraikan format binari atau mengurangkan kos tambahan dalam gelung yang kritikal dari segi prestasi. Jika boleh, utamakan bentuk penutupan with... berbanding peruntukan manual.

// Counting set bits across a byte buffer
let data: [UInt8] = [0b1011, 0b0110, 0b1111]
let bits = data.withUnsafeBufferPointer { buf in
    buf.reduce(0) { $0 + $1.nonzeroBitCount }
}
print(bits) // 3 + 2 + 4 = 9

Semakan Ringkas

Ingat semula ciri tambahan yang diberikan oleh penuding buffer berbanding penuding tunggal.

Ringkasan

Penuding buffer membalut rantau bersebelahan sebagai koleksi terhad:

  • UnsafeBufferPointer / UnsafeMutableBufferPointer = alamat asas + kiraan.
  • Anda mendapat map, filter, reduce dan iterasi for pada memori mentah.
  • Utamakan withUnsafeBufferPointer pada tatasusunan supaya Swift mengurus kesahan dan jangka hayat.
  • Kiraan yang diberikan dipercayai — tentukannya daripada peruntukan sebenar.
Percuma untuk bermula

Pelajari Swift dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
122
Pelajaran
409

Soalan Lazim

Adakah pelajaran “Penuding Penimbal Tidak Selamat” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Swift Academy, termasuk “Penuding Penimbal Tidak Selamat”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Swift Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Penuding Penimbal Tidak Selamat”?

Proses memori bersebelahan dengan cekap. Anda berlatih Swift Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Swift Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Swift Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 3 daripada 4.

Berapa lamakah pelajaran “Penuding Penimbal Tidak Selamat” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Swift Academy ini?

Ya. Setiap pelajaran Swift Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. MemoryLayout dan Penjajaran
  2. UnsafePointer dan UnsafeMutablePointer
  3. Penuding Penimbal Tidak Selamat
  4. withUnsafeBytes dan Interop C
← Kembali ke Swift Academy