Uploaded image for project: 'Swift'
  1. Swift
  2. SR-704

EXC_BAD_ACCESS on returning nil from a failable initializer of NSObject subclass

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Medium
    • Resolution: Done
    • Component/s: None
    • Labels:
    • Environment:

      Description

      Returning nil from a failable initializer of an NSObject subclass results in a runtime crash in swift_deallocPartialClassInstance call. This doesn't happen if a class method is used instead of a convenience initializer, or if the class doesn't inherit from NSObject. The issue does not depend on optimization level. This is a regression from Swift 2.1 / Xcode 7.2 where the same setup doesn't crash.

      Code example

      import Foundation
      
      class MyClass: NSObject {
      
          let property: String
      
          required init(value: String) {
              self.property = value
      
              super.init()
          }
      
          convenience init?(failableValue: String) {
              if failableValue != "" {
                  self.init(value: failableValue)
              } else {
                  return nil
              }
          }
      
          static func instanceWithFailableValue(failableValue: String) -> Self? {
              if failableValue != "" {
                  return self.init(value: failableValue)
              } else {
                  return nil
              }
          }
      
      }
      
      let goodValue = "Don't crash"
      let badValue = ""
      
      // This works correctly
      let goodObject = MyClass(failableValue: goodValue)
      print(goodObject)
      
      // This also works correctly
      let workaround = MyClass.instanceWithFailableValue(badValue)
      print(workaround)
      
      // This crashes upon returning from the initializer
      let badObject = MyClass(failableValue: badValue)
      print(badObject)
      

      Stacktrace

      * thread #1: tid = 0x1792d1, 0x0000000100259f40 DemoProject`swift::Metadata::getClassObject() const, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
        * frame #0: 0x0000000100259f40 DemoProject`swift::Metadata::getClassObject() const
          frame #1: 0x000000010025353e DemoProject`swift_deallocPartialClassInstance + 62
          frame #2: 0x000000010026b9e5 DemoProject`MyClass.init(failableValue="") -> MyClass? + 357 at main.swift:0
          frame #3: 0x000000010026ba42 DemoProject`MyClass.__allocating_init(failableValue : String) -> MyClass? + 66 at main.swift:0
          frame #4: 0x000000010026c70b DemoProject`testFailableInitializer() -> () + 603 at main.swift:42
          frame #5: 0x000000010026b67b DemoProject`main + 75 at main.swift:46
          frame #6: 0x00007fff8edcb5ad libdyld.dylib`start + 1
      

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              slavapestov Slava Pestov
              Reporter:
              vlas Vlas Voloshin
              Votes:
              9 Vote for this issue
              Watchers:
              18 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: