美文网首页
swift--指针与内存绑定

swift--指针与内存绑定

作者: Mjs | 来源:发表于2020-12-14 14:26 被阅读0次

    指针

    Swift中的指针分为两类, typed pointer指定数据类型指针,raw pinter未指定数据类型的指针(原⽣指针)

    raw pinter在Swift中的表示是 UnsafeRawPointer
    typed pointer在Swift中的表示是 UnsafePointer<T>

    Swift Object-C 说明
    unsafePointer<T> const T * 指针及所指向的内容都不可变
    unsafeMutablePointer T * 指针及其所指向的内存内容均可变
    unsafeRawPointer const void * 指针指向未知类型
    unsafeMutableRawPointer void * 指针指向未知类型

    RawPointer使用

    //指针的内存管理是手动管理
    //申请32字节内存空间,8字节对齐方式
    let p = UnsafeMutableRawPointer.allocate(byteCount: 32, alignment: 8)
    
    for i in 0..<4 {
        //advanced 前进字节
        //storeBytes 储存数据
        p.advanced(by: i*8).storeBytes(of: i+1, as: Int.self)
    }
    for i in 0..<4 {
        //读取数据
        let value = p.load(fromByteOffset: i*8, as: Int.self)
        print("index\(i),value:\(value)")
    }
    p.deallocate()
    

    allocate来开辟内存空间

     @inlinable
      public static func allocate(
        byteCount: Int, alignment: Int
      ) -> UnsafeMutableRawPointer {
        var alignment = alignment
        if alignment <= _minAllocationAlignment() {
          alignment = 0
        }
        return UnsafeMutableRawPointer(Builtin.allocRaw(
            byteCount._builtinWordValue, alignment._builtinWordValue))
      }
    

    Builtin是LLVM标准模块。

    unsafePointer

    @inlinable public func withUnsafePointer<T, Result>(to value: T, _ body: (UnsafePointer<T>) throws -> Result) rethrows -> Result
    

    通过rethrows将结果向上级传递

    var age = 10
    let p = withUnsafePointer(to: &age) {
        //单一表达式可省略
        //ptr in return ptr
        $0
    }
    print(p.pointee)
    

    p就是$0,代表UnsafePointer这个对象指针,p.pointee就是值

    var age = 10
    age = withUnsafePointer(to: &age) { ptr in
        return ptr.pointee + 12
    }
    print(age)
    ··········UnsafeMutablePointer
    22
    

    这个时候返回的就是闭包返回值。

    UnsafeMutablePointer

    var age = 10
    withUnsafeMutablePointer(to: &age) { ptr in
        ptr.pointee += 10
    }
    print(p)
    

    UnsafeMutablePointer的区别就是可以直接对原始对象进行修改。

    struct Teacher {
        var age = 10
        var height = 1.85
    }
    
    var t = Teacher()
    
    let ptr = UnsafeMutablePointer<Teacher>.allocate(capacity: 2)
    ptr.initialize(to: Teacher())
    ptr.advanced(by:1).initialize(to: Teacher(age: 18, height: 1.66))
    print(ptr[0])
    print(ptr[1])
    print(ptr.successor().pointee)
    
    //手动管理
    ptr.deinitialize(count: 2)
    ptr.deallocate()
    ··············
    Teacher(age: 10, height: 1.85)
    Teacher(age: 18, height: 1.66)
    Teacher(age: 18, height: 1.66)
    

    内存绑定

    • withMemoryRebound : 临时更改内存绑定类型
      -bindMemory(to: Capacity:) : 更改内存绑定的类型,如果之前没有绑定,那么就是⾸次绑定;如果绑 定过了,会被重新绑定为该类型。
    • assumingMemoryBound: 假定内存绑定,这⾥是告诉编译器:哥们我就是这种类型,你不要检查我 了。
    withMemoryRebound
    
    var age = 10
    let ptr = withUnsafePointer(to: &age){$0}
    ptr.withMemoryRebound(to: UInt64.self, capacity: 1) { (ptr: UnsafePointer<UInt64>) in
        print(ptr.pointee)
    }
    
    bindMemory

    结合之前学过的

    
    struct HeapObject {
        var kind: UnsafeRawPointer
        var strongref: UInt32
        var unownedRef:UInt32
    }
    struct _swift_class {
        var kind: UnsafeRawPointer
        var superClass: UnsafeRawPointer
        var cachedata1: UnsafeRawPointer
        var cachedata2: UnsafeRawPointer
        var data: UnsafeRawPointer
        var flags: UInt32
        var instanceAddressOffset: UInt32
        var instanceSize: UInt32
        var flinstanceAlignMask: UInt16
        var reserved: UInt16
        var classSize: UInt32
        var classAddressOffset: UInt32
        var description: UnsafeRawPointer
        
    }
    class Teacher {
        var age = 18
    }
    var t = Teacher()
    //相当于OCheCF交互方式,__bridge 所有权转变,转为指针
    //passUnretained非retain
    let ptr = Unmanaged.passUnretained(t as AnyObject).toOpaque()
    //bindMemory 重新绑定类型
    let hep = ptr.bindMemory(to: HeapObject.self, capacity: 1)
    let meta = hep.pointee.kind.bindMemory(to: _swift_class.self, capacity: 1)
    
    print(meta.pointee)
    ···················
    _swift_class(kind: 0x0000000100004140, superClass: 0x00007fff97884f98, cachedata1: 0x00007fff6c7cf3d0, cachedata2: 0x0000002000000000, data: 0x0000000101a0eed2, flags: 2, instanceAddressOffset: 0, instanceSize: 24, flinstanceAlignMask: 7, reserved: 0, classSize: 136, classAddressOffset: 16, description: 0x0000000100002be8)
    

    这样我们就可以查看metadata.

    assumingMemoryBound
    var tul = (10,20)
    func testPointer(_ p :UnsafePointer<Int>){
        print(p[0],p[1])
    }
    withUnsafePointer(to: &tul) {  (tulPtr : UnsafePointer<(Int,Int)>) in
        //assumingMemoryBound 假定类型 告诉编译器类型,不需要检查
        testPointer(UnsafeRawPointer(tulPtr).assumingMemoryBound(to: Int.self))
    }
    ··············
    10 20
    

    直接获取地址。

    内存绑定是不安全的,需要我们自己掌控

    相关文章

      网友评论

          本文标题:swift--指针与内存绑定

          本文链接:https://www.haomeiwen.com/subject/cucygktx.html