Segmentation fault vs Variable ... used before being initialized

We got a segmentation fault on our Testflight build (not on debug builds). The build was created with the latest xCode version, the code is written in Swift (SwiftUI).

Luckily, one developer still uses an older version of xCode (12.4) and realised that the code doesn't compile for that version. We get a "Variable ... used before being initialized" compiler error.

Turns out that fixing the compiler error also fixes the segmentation fault crash.

    @Binding var playingId: Int?
    @State var player: AVPlayer
    init(playingId: Binding<Int?>,) {
        self.player = AVPlayer()
        self._playingId = playingId
    }

changed to:

    @Binding var playingId: Int?
    @State var player: AVPlayer = AVPlayer()
    init(playingId: Binding<Int?>,) {
       self._playingId = playingId
    }

So, I wonder where the problem lies:

  • Is this a compiler bug in the newest version?
  • A runtime problem?
  • Or a problem in the language definition?
Answered by Claude31 in 684126022

The fact is that this does not initialise a State var

        self.player = AVPlayer()

if you add a print just after, you'll see it

        print("Just after init", self.player)

What is surprising and worth a bug report is the change in compiler behaviour between the Xcode releases. Please post the bug report reference and don't forget to close the thread.

No link with the problem, but why the comma after parameter            init(playingId: Binding<Int?>,) {

The original code compiles but has 8 arguments for init (by compiles I mean that the corrected one compiles for all version of xCode we tested with.

The comma in init is my mistake. I forgot to remove it when I removed the other arguments from init to illustrate the problem here. Sorry for that (I think I cannot edit the question any longer).

Thank you Claude31 for pointing this out.

init() in SwiftUI for State var is a bit tricky:

https://www.hackingwithswift.com/forums/swiftui/why-no-setting-of-intial-state/2021

Something like this should work:

    @Binding var playingId: Int?
    @State var player: AVPlayer!

    init(playingId: Binding<Int?>, player: AVPlayer) {
        _player = State(initialValue: player)
        self._playingId = playingId
    }
Accepted Answer

The fact is that this does not initialise a State var

        self.player = AVPlayer()

if you add a print just after, you'll see it

        print("Just after init", self.player)

What is surprising and worth a bug report is the change in compiler behaviour between the Xcode releases. Please post the bug report reference and don't forget to close the thread.

Is this a compiler bug in the newest version?

why would we trade a compiler error for a runtime crash

Isn't it clear it is a compiler bug?

According to the accepted proposal of propertyWrapper (SE-0258Property Wrappers), declaring an @State variable is something similar to this:

private var _player: State<AVPlayer> = State<AVPlayer>(wrappedValue: 1738)
var player: AVPlayer {
  get { return _player.wrappedValue }
  set { _player.wrappedValue = newValue }
}

(Simplified to illustrate the problem.)

As you see, the property player is a computed property, so, based on the initialization rule of Swift, it will be available only after all the stored properties are initialized.

Swift compiler should mark the line self.player = AVPlayer() error. You can send a bug report to Apple or swift.org.


By the way, creating a useless instance like AVPlayer() is not recommended. You should use Optional if you cannot use AVPlayer.init(url:) or AVPlayer.init(playerItem:) at the time of initialization.

Segmentation fault vs Variable ... used before being initialized
 
 
Q