LoginSignup
2
1

More than 5 years have passed since last update.

UnsafeMutableRawPointerの中身が解放されない。。。

Last updated at Posted at 2017-11-12

Swiftバージョン

terminal.txt
$ swift --version
Apple Swift version 4.0.2 (swiftlang-900.0.69.2 clang-900.0.38)
Target: x86_64-apple-macosx10.9

結論

UnsafeMutableRawPointerの deallocate(bytes:, alignedTo:) メソッドを呼んでも
initializeMemory(as:, to:) メソッドでバインドしたインスタンスは解放されない。

回避策として、一旦 UnsafeMutablePointer<T> に変換してから、こちらのメソッドを通して解放する

解放されないコード

解放されないコード.swift
voidPointer.deallocate(bytes: MemoryLayout<Foo>.stride, alignedTo: MemoryLayout<Foo>.alignment)

解放されるコード

解放されるコード.swift
// UnsafeMutabeRawPointerをUnsafeMutablePointerに変換しています
let opaque = OpaquePointer(self.voidPointer)
let fooPointer = UnsafeMutablePointer<Foo>(opaque)

// UnsafeMutablePointerを通して解放すると問題なく解放される
fooPointer.deinitialize(count: 1) //ただしこれがないとだめ
fooPointer.deallocate(capacity: MemoryLayout<Foo>.size)

詳細

解放されないコード.swift

[gist] 開放されないコード

解放されないコード.swift
class Foo {
    // 呼ばれない
    deinit {
        print(type(of: self), #function)
    }
}

class Main {
    var voidPointer: UnsafeMutableRawPointer
    init(voidPointer: UnsafeMutableRawPointer) {
        self.voidPointer = voidPointer
    }

    deinit {
        print(type(of: self), #function)

        // ここでFooインスタンスを解放しているが、解放されない
        voidPointer.deallocate(bytes: MemoryLayout<Foo>.stride, alignedTo: MemoryLayout<Foo>.alignment)
    }
}

do {
    let f = Foo()
    let fp = UnsafeMutableRawPointer.allocate(bytes: MemoryLayout<Foo>.size, alignedTo: 1)
    fp.initializeMemory(as: Foo.self, to: f)
    let _ = Main(voidPointer: fp)
}

解放されるコード

[gist] 解放されるコード

解放されるコード.swift
class Foo {
    // 呼ばれる
    deinit {
        print(type(of: self), #function)
    }
}

class Main {
    var voidPointer: UnsafeMutableRawPointer
    init(voidPointer: UnsafeMutableRawPointer) {
        self.voidPointer = voidPointer
    }

    deinit {
        print(type(of: self), #function)

        // UnsafeMutablePointerへ一旦変換してから解放する
        let opaque = OpaquePointer(self.voidPointer)
        let fooPointer = UnsafeMutablePointer<Foo>(opaque)
        fooPointer.deinitialize(count: 1) 
        fooPointer.deallocate(capacity: MemoryLayout<Foo>.size)
    }
}

do {
    let f = Foo()
    let fp = UnsafeMutableRawPointer.allocate(bytes: MemoryLayout<Foo>.size, alignedTo: 1)
    fp.initializeMemory(as: Foo.self, to: f)
    let _ = Main(voidPointer: fp)
}

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1