iOS 12 错误 swift_getAssociatedTypeWitnessSlowImpl EXC_BAD_ACCESS 汇编代码

iOS 12 error swift_getAssociatedTypeWitnessSlowImpl EXC_BAD_ACCESS in assembly code

我正在用 Combine 和 SwiftUI 编写一个项目,向后兼容 iOS 12/11 与 RxSwift、RxCocoa 和 UIKit。我的项目基于很多协议、关联类型和泛型。当我在 运行 iOS 13 上的项目工作正常但在 iOS 12 上应用程序突然崩溃。

我正在尝试对 Redux 架构进行一些更改。我有 reducer、actions(作为枚举)、stores 和 store providers(store provider 旨在实例化两个商店:rxstore 和 combinestore 。(我知道这不是最好的方法,但我想了解为什么这个错误发生)。

我还有一个所谓的ReduxArchiver和一个ReduxArchiverElement。这个 (ReduxArchiver) 就像一个监听器或一个用于处理和保存 redux 存储更改的委托。 (我也知道这不是最好的解决方案)。当商店有新状态时,ReduxArchiver 处理更改,根据需要修改数据并决定是否将状态保存在磁盘上。 Archiver 还旨在在实例化商店时从磁盘加载应用程序状态。

错误是 Thread 1: EXC_BAD_ACCESS (code=1, address=0x10) 并且在我实例化 ReduxArchiver 类型的对象时出现。这是因为 ReduxArchiverElement<T: Codable> 数组的实例化(请参阅下面或此处的代码:https://github.com/mariusjcb/CrossReduxSOA

有时会出现在控制台中:

libMobileGestalt MobileGestalt.c:890: MGIsDeviceOneOfType is not supported
 on this platform.

我不知道这是我的错还是只是一个 swift 错误,因为项目中关联的 types/generics 太多。

我将 combine 和 swiftui 都链接为弱框架,因此缺少 SwiftUI/Combine.

没有问题

我的框架和库也嵌入到目标设置中 Embed & Sign

实际错误:

Thread 1: EXC_BAD_ACCESS (code=1, address=0x10)

当我在做 po $arg1:

// On #0    0x0000000108f6a93f in swift_getWitnessTable ():
(lldb) po $arg1
<nil>

// On #16   0x0000000108f6b308 in swift_getAssociatedTypeWitness ():
(lldb) po $arg1
error: Couldn't materialize: couldn't read the value of register rdi
error: errored out in DoExecute, couldn't PrepareToExecuteJITExpression

当我检查 $rdi:

//Xcode: 11.2
(lldb) register read
General Purpose Registers:
       rbx = 0x000000010ff7bdb8  libswiftCore.dylib`InitialAllocationPool + 4304
       rbp = 0x00007ffee39a3990
       rsp = 0x00007ffee39a3960
       r12 = 0x000000010cc69448  Models`protocol requirements base descriptor for Redux.Reducer
       r13 = 0x00000000000000ff
       r14 = 0x000000010cc69478  Models`associated type descriptor for StateType
       r15 = 0x000000010d1ba718  type metadata for Reducers.ExampleReducer
       rip = 0x000000010fea2308  libswiftCore.dylib`swift_getAssociatedTypeWitness + 152
13 registers were unavailable.

//Xcode 11.1
(lldb) register read --all 
General Purpose Registers:
       rax = 0x0000000000000000
       rbx = 0x0000000105d1db74  Models`protocol conformance descriptor for Models.ExampleModel : Swift.Identifiable in Models + 16
       rcx = 0x0000000000000000
       rdx = 0x0000000000030000
       rdi = 0x0000000000000000
       rsi = 0x0000000105d1db78  Models`protocol conformance descriptor for Models.ExampleModel : Swift.Identifiable in Models + 20
       rbp = 0x00007ffeea8fa960
       rsp = 0x00007ffeea8fa8d0
        r8 = 0x0000000000000000
        r9 = 0x0000000105d1db50  Models`protocol conformance descriptor for Models.ExampleModel : Swift.Encodable in Models + 20
       r10 = 0x0000000108fc10a4  libswiftCore.dylib`method descriptor for Swift.Encodable.encode(to: Swift.Encoder) throws -> ()
       r11 = 0x0000000000000001
       r12 = 0x0000000105d9c3b0  Models`__unnamed_24
       r13 = 0x0000000000000000
       r14 = 0x0000000105d1db74  Models`protocol conformance descriptor for Models.ExampleModel : Swift.Identifiable in Models + 16
       r15 = 0x0000000105d1db64  Models`protocol conformance descriptor for Models.ExampleModel : Swift.Identifiable in Models
       rip = 0x0000000108f6a93f  libswiftCore.dylib`swift_getWitnessTable + 447
    rflags = 0x0000000000000247
        cs = 0x000000000000002b
        fs = 0x0000000000000000

对象的实例化:

// In AppDelegate (as property):
// ...

let state = ExampleStoreBuilder.build()

// The Build Method from ExampleStoreBuilder

let archiveListeners = [GenericReduxArchiverLogger("example_archiver")]
        var listeners: [ReduceStoreOutputDelegate] = [GenericReduxStoreLogger("example_logger")]
ERROR>> let defaultStoreArchiver = ExampleArchiver<ExampleRxStore>(outputDelegates: archiveListeners) <<<< Error: EXC_BAD_ACCESS

        listeners.append(defaultStoreArchiver)
        listeners.append(contentsOf: archiveListeners)
        if #available(iOS 13.0, *) {
            listeners.append(ExampleArchiver<ExampleCombineStore>(outputDelegates: archiveListeners))
        }

        let reducer = ExampleReduceBuilder.build()
        let initialState = defaultStoreArchiver.statesHistory.last?.state ?? .emptyState
        return ReduxState<ExampleStoreProvider<ExampleReducer>>(initialState,
                                                              reducedBy: reducer,
                                                              outputDelegates: listeners)

来自 let defaultStoreArchiver 的 EXC_BAD_ACCESS 位于 ExampleArchiver 线上:

public var statesHistory = [ReduxArchiveElement<StoreType.ReducerType.StateType>]()

ReduxArchiverElement 定义为:

public struct ReduxArchiveElement<T: Codable>: Codable {
    public let date: Date
    public let state: T

    public init(date: Date, state: T) {
        self.date = date
        self.state = state
    }
}

最后 StoreType 和 Reducer 定义为:

// ReduceStoreInitializable protocol
public protocol ReduceStoreInitializable {
    associatedtype ReducerType: Reducer
...


// Store:
public protocol ReduceStore: class, ReduceStoreInitializable {
    var reducer: ReducerType! { get set }
...

// Reducer:
public protocol Reducer: class {
    associatedtype ActionType
    associatedtype ItemType: Codable
    associatedtype StateType: Codable
    associatedtype ErrorType: Error

关于堆栈的实际错误:

Thread 1 Queue : com.apple.main-thread (serial)

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x10)
    frame #0: 0x00000001063746e4 libswiftCore.dylib`swift_getWitnessTable + 392
    frame #1: 0x0000000105802e38 Models`lazy protocol witness table accessor for type ExampleModel and conformance ExampleModel at <compiler-generated>:0
    frame #2: 0x0000000105802cf4 Models`instantiation function for generic protocol witness table for ExampleModel at <compiler-generated>:0
    frame #3: 0x0000000106374c08 libswiftCore.dylib`swift_getWitnessTable + 1708
    frame #4: 0x0000000106385ee8 libswiftCore.dylib`swift::TargetProtocolConformanceDescriptor<swift::InProcess>::getWitnessTable(swift::TargetMetadata<swift::InProcess> const*) const + 496
    frame #5: 0x0000000105112fd8 ExampleApp-SwiftUI`swift::swift50override_conformsToProtocol(swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptor<swift::InProcess> const*, swift::TargetWitnessTable<swift::InProcess> const* (*)(swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptor<swift::InProcess> const*)) + 60
    frame #6: 0x00000001063607fc libswiftCore.dylib`swift::_conformsToProtocol(swift::OpaqueValue const*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptorRef<swift::InProcess>, swift::TargetWitnessTable<swift::InProcess> const**) + 44
    frame #7: 0x00000001063863b0 libswiftCore.dylib`swift::_checkGenericRequirements(llvm::ArrayRef<swift::TargetGenericRequirementDescriptor<swift::InProcess> >, std::__1::vector<void const*, std::__1::allocator<void const*> >&, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 1160
    frame #8: 0x0000000106383410 libswiftCore.dylib`(anonymous namespace)::DecodedMetadataBuilder::createBoundGenericType(swift::TargetContextDescriptor<swift::InProcess> const*, llvm::ArrayRef<swift::TargetMetadata<swift::InProcess> const*>, swift::TargetMetadata<swift::InProcess> const*) const + 576
    frame #9: 0x0000000106382ac4 libswiftCore.dylib`swift::Demangle::TypeDecoder<(anonymous namespace)::DecodedMetadataBuilder>::decodeMangledType(swift::Demangle::Node* const&) + 2832
    frame #10: 0x0000000106382100 libswiftCore.dylib`swift::Demangle::TypeDecoder<(anonymous namespace)::DecodedMetadataBuilder>::decodeMangledType(swift::Demangle::Node* const&) + 332
    frame #11: 0x00000001063819e8 libswiftCore.dylib`swift_getTypeByMangledNodeImpl(swift::MetadataRequest, swift::Demangle::Demangler&, swift::Demangle::Node*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 460
    frame #12: 0x00000001063817a8 libswiftCore.dylib`swift::swift_getTypeByMangledNode(swift::MetadataRequest, swift::Demangle::Demangler&, swift::Demangle::Node*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 520
    frame #13: 0x0000000106381d18 libswiftCore.dylib`swift_getTypeByMangledNameImpl(swift::MetadataRequest, llvm::StringRef, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 648
    frame #14: 0x0000000106380110 libswiftCore.dylib`swift::swift_getTypeByMangledName(swift::MetadataRequest, llvm::StringRef, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 520
    frame #15: 0x0000000106376a6c libswiftCore.dylib`swift_getAssociatedTypeWitnessSlowImpl(swift::MetadataRequest, swift::TargetWitnessTable<swift::InProcess>*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolRequirement<swift::InProcess> const*, swift::TargetProtocolRequirement<swift::InProcess> const*) + 492
    frame #16: 0x0000000106375018 libswiftCore.dylib`swift_getAssociatedTypeWitness + 176
    frame #17: 0x00000001056df53c Stores`ExampleArchiver.init(storeLocation=nil, outputDelegates=1 value, self=0x00000001c0463840) at ExampleArchiver.swift:18:85
    frame #18: 0x00000001056df38c Stores`ExampleArchiver.__allocating_init(storeLocation:outputDelegates:) at ExampleArchiver.swift:0
    frame #19: 0x00000001056ebc48 Stores`static ExampleStoreBuilder.build(self=Stores.ExampleStoreBuilder) at ExampleStoreBuilder.swift:23:64
    frame #20: 0x0000000105000d20 ExampleApp-SwiftUI`AppDelegate.init() at AppDelegate.swift:17:36
    frame #21: 0x0000000105000e28 ExampleApp-SwiftUI`@objc AppDelegate.init() at <compiler-generated>:0
    frame #22: 0x000000018e4a8a00 UIKit`_UIApplicationMainPreparations + 1688
    frame #23: 0x000000018e39d724 UIKit`UIApplicationMain + 184
    frame #24: 0x0000000105001404 ExampleApp-SwiftUI`main at AppDelegate.swift:14:7
  * frame #25: 0x0000000183e11fc0 libdyld.dylib`start + 4

for #16 0x0000000106375018 in swift_getAssociatedTypeWitness () 实际程序集如下所示:

libswiftCore.dylib`swift_getAssociatedTypeWitness:
    0x106374f68 <+0>:   stp    x24, x23, [sp, #-0x40]!
    0x106374f6c <+4>:   stp    x22, x21, [sp, #0x10]
    0x106374f70 <+8>:   stp    x20, x19, [sp, #0x20]
    0x106374f74 <+12>:  stp    x29, x30, [sp, #0x30]
    0x106374f78 <+16>:  add    x29, sp, #0x30            ; =0x30 
    0x106374f7c <+20>:  mov    x23, x0
    0x106374f80 <+24>:  sub    x8, x4, x3
    0x106374f84 <+28>:  lsr    x8, x8, #3
    0x106374f88 <+32>:  ldr    x0, [x1, w8, uxtw #3]
    0x106374f8c <+36>:  tbnz   w0, #0x0, 0x106374fa8     ; <+64>
    0x106374f90 <+40>:  mov    x1, #0x0
    0x106374f94 <+44>:  ldp    x29, x30, [sp, #0x30]
    0x106374f98 <+48>:  ldp    x20, x19, [sp, #0x20]
    0x106374f9c <+52>:  ldp    x22, x21, [sp, #0x10]
    0x106374fa0 <+56>:  ldp    x24, x23, [sp], #0x40
    0x106374fa4 <+60>:  ret    
    0x106374fa8 <+64>:  mov    x19, x4
    0x106374fac <+68>:  mov    x20, x3
    0x106374fb0 <+72>:  mov    x21, x2
    0x106374fb4 <+76>:  mov    x22, x1
    0x106374fb8 <+80>:  adr    x0, #0xcd130              ; swift_getAssociatedTypeWitnessSlow::Predicate
    0x106374fbc <+84>:  nop    
    0x106374fc0 <+88>:  adr    x1, #0x3690               ; swift_getAssociatedTypeWitnessSlow::$_8::__invoke(void*)
    0x106374fc4 <+92>:  nop    
    0x106374fc8 <+96>:  mov    x2, #0x0
    0x106374fcc <+100>: bl     0x106385ad4               ; swift_once
    0x106374fd0 <+104>: nop    
    0x106374fd4 <+108>: ldr    x8, #0xcd10c              ; swift_getAssociatedTypeWitnessSlow::Override
    0x106374fd8 <+112>: cbz    x8, 0x106375000           ; <+152>
    0x106374fdc <+116>: adr    x5, #0x18a4               ; swift_getAssociatedTypeWitnessSlowImpl(swift::MetadataRequest, swift::TargetWitnessTable<swift::InProcess>*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolRequirement<swift::InProcess> const*, swift::TargetProtocolRequirement<swift::InProcess> const*)
    0x106374fe0 <+120>: nop    
    0x106374fe4 <+124>: mov    x0, x23
    0x106374fe8 <+128>: mov    x1, x22
    0x106374fec <+132>: mov    x2, x21
    0x106374ff0 <+136>: mov    x3, x20
    0x106374ff4 <+140>: mov    x4, x19
    0x106374ff8 <+144>: blr    x8
    0x106374ffc <+148>: b      0x106374f94               ; <+44>
    0x106375000 <+152>: mov    x0, x23
    0x106375004 <+156>: mov    x1, x22
    0x106375008 <+160>: mov    x2, x21
    0x10637500c <+164>: mov    x3, x20
    0x106375010 <+168>: mov    x4, x19
    0x106375014 <+172>: bl     0x106376880               ; swift_getAssociatedTypeWitnessSlowImpl(swift::MetadataRequest, swift::TargetWitnessTable<swift::InProcess>*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolRequirement<swift::InProcess> const*, swift::TargetProtocolRequirement<swift::InProcess> const*)
->  0x106375018 <+176>: b      0x106374f94               ; <+44>    <<< Thread 1: EXC_BAD_ACCESS (code=1, address=0x10)

同样对于 swift_getWitnessTable 中的 #0 0x00000001063746e4 () asm 看起来像:

    0x106374660 <+260>:  adr    x26, #0xb57a0             ; AllocationPool
    0x106374664 <+264>:  nop    
    0x106374668 <+268>:  str    x21, [sp, #0x30]
    0x10637466c <+272>:  ldar   x24, [x28]
    0x106374670 <+276>:  cbnz   x24, 0x1063747c8          ; <+620>
    0x106374674 <+280>:  b      0x106374688               ; <+300>
    0x106374678 <+284>:  add    x8, x24, #0x8             ; =0x8 
    0x10637467c <+288>:  csel   x28, x24, x8, lo
    0x106374680 <+292>:  ldar   x24, [x28]
    0x106374684 <+296>:  cbnz   x24, 0x1063747c8          ; <+620>
    0x106374688 <+300>:  cbnz   x23, 0x1063747b0          ; <+596>
    0x10637468c <+304>:  ldrsw  x9, [x20]
    0x106374690 <+308>:  cbz    w9, 0x1063746a8           ; <+332>
    0x106374694 <+312>:  and    x8, x9, #0xfffffffffffffffe
    0x106374698 <+316>:  add    x8, x8, x20
    0x10637469c <+320>:  tbz    w9, #0x0, 0x1063746ac     ; <+336>
    0x1063746a0 <+324>:  ldr    x8, [x8]
    0x1063746a4 <+328>:  b      0x1063746ac               ; <+336>
    0x1063746a8 <+332>:  mov    x8, #0x0
    0x1063746ac <+336>:  ldr    w12, [x20, #0xc]
    0x1063746b0 <+340>:  ubfx   x9, x12, #6, #1
    0x1063746b4 <+344>:  add    x10, x21, x9, lsl #2
    0x1063746b8 <+348>:  ubfx   x11, x12, #8, #8
    0x1063746bc <+352>:  madd   x9, x11, x14, x10
    0x1063746c0 <+356>:  ubfx   x13, x12, #16, #1
    0x1063746c4 <+360>:  add    x9, x9, x13, lsl #2
    0x1063746c8 <+364>:  tbnz   w12, #0x10, 0x1063746d4   ; <+376>
    0x1063746cc <+368>:  mov    x10, #0x0
    0x1063746d0 <+372>:  b      0x1063746dc               ; <+384>
    0x1063746d4 <+376>:  mul    x11, x11, x14
    0x1063746d8 <+380>:  ldr    w10, [x10, x11]
    0x1063746dc <+384>:  add    x9, x9, x10, lsl #3
    0x1063746e0 <+388>:  ldrh   w9, [x9, #0x2]
->  0x1063746e4 <+392>:  ldr    w8, [x8, #0x10]   <<< ERROR; I don't understand this line... :(

我不完全理解问题的根本原因,但我能够通过删除对我的一个协议的 Identifiable 一致性来解决这个问题。我的部署目标是 iOS 10,所以事后看来,我不确定为什么我的框架能够在没有 @available 检查的情况下编译。

在构建设置中,针对您的项目寻找

DEAD_CODE_STRIPPING = No

应该可以解决问题。