【发布时间】:2020-05-30 03:39:18
【问题描述】:
我从我的 Mac 应用程序中收到了一些奇怪的崩溃日志。这是崩溃的线程:
OS Version: Mac OS X 10.14.6 (18G103)
Report Version: 104
Exception Type: SIGSEGV
Exception Codes: SEGV_MAPERR at 0x0
Crashed Thread: 8
Thread 8 Crashed:
0 ??? 0x0000000000000000 0x0 + 0
1 libswiftCore.dylib 0x00007fff79a743f3 swift_getSingletonMetadata + 578
2 PowerPhotos 0x000000010323f30d type metadata accessor for PowerPhotos.IPAssetCollectionUpdate (<compiler-generated>:0)
3 libswiftCore.dylib 0x00007fff79a8c94c swift::TargetProtocolConformanceDescriptor<swift::InProcess>::getCanonicalTypeMetadata() const + 171
4 libswiftCore.dylib 0x00007fff79a8da24 swift_conformsToSwiftProtocolImpl(swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptor<swift::InProcess> const*, llvm::StringRef) + 291
5 libswiftCore.dylib 0x00007fff79a8d884 swift_conformsToProtocolImpl(swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptor<swift::InProcess> const*) + 99
6 PowerPhotos 0x000000010339e7a9 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*)) + 56
7 libswiftCore.dylib 0x00007fff79a6215a swift::_conformsToProtocol(swift::OpaqueValue const*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptorRef<swift::InProcess>, swift::TargetWitnessTable<swift::InProcess> const**) + 41
8 libswiftCore.dylib 0x00007fff79a65f97 _conformsToProtocols(swift::OpaqueValue const*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetExistentialTypeMetadata<swift::InProcess> const*, swift::TargetWitnessTable<swift::InProcess> const**) + 230
9 libswiftCore.dylib 0x00007fff79a65369 _dynamicCastToExistential(swift::OpaqueValue*, swift::OpaqueValue*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetExistentialTypeMetadata<swift::InProcess> const*, swift::DynamicCastFlags) + 488
10 libswiftCore.dylib 0x00007fff79836517 Swift._print_unlocked<A, B where B: Swift.TextOutputStream>(A, inout B) -> () + 550
11 PowerPhotos 0x00000001031e2483 PowerPhotos.IPArchiveUpdateOperation.(loadFromReplay in _C3BCBD43848FA0F2A85DA8591115A6A7)() -> PowerPhotos.IPArchiveLoadResult (<compiler-generated>:0)
12 PowerPhotos 0x00000001031e1700 PowerPhotos.IPArchiveUpdateOperation.(loadFromPreferredDatabase in _C3BCBD43848FA0F2A85DA8591115A6A7)() -> (PowerPhotos.IPArchiveLoadResult, Swift.Error?) (IPArchiveUpdateOperation.swift:430)
13 PowerPhotos 0x00000001031e08fa PowerPhotos.IPArchiveUpdateOperation.perform() throws -> Any (IPArchiveUpdateOperation.swift:218)
14 PowerPhotos 0x00000001031e179c @objc PowerPhotos.IPArchiveUpdateOperation.perform() throws -> Any (<compiler-generated>:0)
15 BWFoundation 0x00000001036c8173 -[BWOperation main] (BWOperation.m:124)
16 PowerPhotosKit 0x0000000103898e71 -[IPOperation main] (IPOperation.m:287)
17 Foundation 0x00007fff502f5ced -[__NSOperationInternal _start:] + 684
18 Foundation 0x00007fff5031fca7 __NSOQSchedule_f + 226
19 libdispatch.dylib 0x00007fff7a0055f8 _dispatch_call_block_and_release + 11
20 libdispatch.dylib 0x00007fff7a00663d _dispatch_client_callout + 7
21 libdispatch.dylib 0x00007fff7a008de6 _dispatch_continuation_pop + 413
22 libdispatch.dylib 0x00007fff7a0084a3 _dispatch_async_redirect_invoke + 702
23 libdispatch.dylib 0x00007fff7a0143bc _dispatch_root_queue_drain + 323
24 libdispatch.dylib 0x00007fff7a014b46 _dispatch_worker_thread2 + 89
25 libsystem_pthread.dylib 0x00007fff7a2466b3 _pthread_wqthread + 582
26 libsystem_pthread.dylib 0x00007fff7a2463fd start_wqthread + 12
27 ??? 0x0000000054485244 0x0 + 0
第 11 帧是最后一次看到我自己的代码,那行代码如下所示:
return IPArchiveLoadResult(error: NSError(description: "Replay did not complete \(replayDatabase.replayState.debugDescription)"))
所以看起来对 debugDescription 的调用正在生成堆栈跟踪的其余部分,以创建该插值字符串。这最终在第 3 帧中结束,该帧引用了“PowerPhotos.IPAssetCollectionUpdate 的类型元数据访问器”。
但奇怪的是:IPAssetCollectionUpdate 与调用这些东西的代码完全无关。它位于应用程序的完全不同的部分。所以我认为这触发了 Swift 在这里执行的任何元数据加载,这主要是巧合。
查看 IAssetCollectionUpdate,我想我明白了可能是什么原因造成的:
@available(OSX 10.15, *)
struct IPAssetCollectionUpdate {
let assetCollection: PHAssetCollection
let diff: CollectionDifference<PHAsset>
}
请注意,IPAssetCollectionUpdate 被标记为仅在 macOS 10.15 上可用,并且崩溃都发生在 macOS 10.14 上。 PHAssetCollection 和 PHAsset 在 macOS 10.14 上确实存在,但 CollectionDifference 不存在。这在应用程序的其余部分不是问题,因为所有内容都受 @available 指令保护,但似乎 Swift 运行时仍在尝试挖掘此结构并生成一些内部元数据并在它不能时爆炸处理 CollectionDifference。或者类似的东西?
无论如何,这就是设置,所以我的问题是:
- 这应该被认为是一个 Swift 错误吗?似乎所有内容都正确注释了可用性指令,我应该能够在 macOS 10.14 上发布它并且不会发生崩溃,因为我在 10.14 上根本没有真正使用过这个结构。
- 不管是谁的错,有什么办法可以更改此代码,使其不会在 10.14 上崩溃?我能想到的最好的办法是将它分解为我的应用程序中的可加载包,并在 10.15 上运行时手动加载包。不过,对于这个愚蠢的问题,这似乎需要做很多工作,我想知道是否有其他更简单的方法来处理这个问题。
我正在使用 Xcode 11.5 和 Swift 5 进行编译。
【问题讨论】: