post Image
【バグ】NSObject を継承したオブジェクトを unowned プロパティーとして保持すると、それを保持しているインスタンスを print すると落ちる

TL;DR

下記のようなコードは落ちます:

import Foundation

class C: NSObject {

}

struct D {
    unowned let x: C
}

let c = C()
let d = D(x: c) // Playground ではここで落ちる
print(d) // シミュレーターや実機ではここで落ちる

どういうことか

自作ライブラリー NotAutoLayout をメンテナンスして、とある修正を対応している時に、新しくできたものがどうしても Playground だけで落ちて、まったく同じコードでも Test でも普通に動くしシミュレーターで確認しても何の問題もありませんでした。

ちなみに実際それを再現するブランチをこちらから落とせます:
https://github.com/el-hoshino/NotAutoLayout/tree/Playground-Bug

上記のものを落として、Workspace を開いてシミュレーターを Target にビルドして Playground 開くと、確実に parent.nal.layout(child) { $0 のクロージャーの終了場所で EXC_BAD_ACCESS で落ちるのです。しかし、Test にまったく同じコードがありますが、そちらは何の問題もなくテストが通ります。Playground は当然ながら lldb も使えないし Call Stack も表示されないので、落ちたとしても具体的になぜ落ちたかもわかりません。

この問題を Discord に投げてみたら、@kishikawakatsumi さんと @rintaro さんのおかげで、原因がようやく突き止められて、最終的には上の TL;DR で出したコードとなります。

具体的に言いますと、NSObject を継承したオブジェクトを class や struct の unowned プロパティーとして保持した際に、どうやら swift_ClassMirror_subscript() のバグで、これを強参照として読み取ろうとしているのが原因だそうです。現在このバグはこちらにも上がっています:
https://bugs.swift.org/browse/SR-5289

このバグを再現するには 2 つの条件が必要です:

  1. プロパティーの型は NSObject を継承する必要があります(つまりそうではない通常の class は問題ありません)
  2. プロパティーを unowned として保持する必要があります(つまり通常の強参照と weak による弱参照の保持も問題ありません)

上記 2 つの条件を満足した場合、そのプロパティーを持つインスタンスを print しようとすると落ちます。

また、Playground で動かす場合は、そもそも作られたものを全てとりあえず print しようとしているので、作られた時点で落ちます。ツラい。

以上、改めまして、この現象の原因を究明するのにお世話になりました @kishikawakatsumi さんと @rintaro さんに、大変ありがとうございます。


『 Swift 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。