EXC_BAD_ACCESS KERN_INVALID_ADDRESS 结构 Decodable.init(来自:)

EXC_BAD_ACCESS KERN_INVALID_ADDRESS on Struct Decodable.init(from:)

我有一个功能,最多可以同时 运行 两次从 API 中获取信息。在 Google Crashlytics 中,我看到不少用户受到此崩溃的影响,但我从未见过类似的情况,我不确定从这里该何去何从。

方法的核心:

URLSession.shared.dataTask(with: urlRequest) { (data, res, err) in
    guard let data = data else { return }
    do {
        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .formatted(self.dateFormatter)
        let json = try decoder.decode([String: TokenResponse].self, from: data)
    }
    catch {
        print(error.localizedDescription)
    }
}.resume()

令牌响应:

struct TokenResponse: Decodable {
    var ticket : String
    var expiration : Date?
    var sessionId: String
}

堆栈跟踪:

Crashed: com.apple.NSURLSession-delegate
0  libicucore.A.dylib             0xe4874 icu::Calendar::clear() + 168
1  CoreFoundation                 0x57ab4 __cficu_ucal_clear + 28
2  CoreFoundation                 0x57ab4 __cficu_ucal_clear + 28
3  CoreFoundation                 0xca884 CFDateFormatterGetAbsoluteTimeFromString + 396
4  CoreFoundation                 0xe0490 CFDateFormatterCreateDateFromString + 108
5  Foundation                     0x1c2dc getObjectValue + 272
6  Foundation                     0x9f300 -[NSDateFormatter getObjectValue:forString:errorDescription:] + 200
7  Foundation                     0xbb5d0 -[NSDateFormatter dateFromString:] + 64
8  libswiftFoundation.dylib       0x37a58 __JSONDecoder.unbox(_:as:) + 592
9  libswiftFoundation.dylib       0x21064 __JSONDecoder.unbox_(_:as:) + 452
10 libswiftFoundation.dylib       0x1e040 _JSONKeyedDecodingContainer.decode<A>(_:forKey:) + 848
11 libswiftFoundation.dylib       0x27a48 protocol witness for KeyedDecodingContainerProtocol.decode<A>(_:forKey:) in conformance _JSONKeyedDecodingContainer<A> + 56
12 libswiftFoundation.dylib       0x258e0 protocol witness for KeyedDecodingContainerProtocol.decode<A>(_:forKey:) in conformance _JSONKeyedDecodingContainer<A> + 36
13 libswiftCore.dylib             0x549a8 KeyedDecodingContainerProtocol.decodeIfPresent<A>(_:forKey:) + 648
14 libswiftFoundation.dylib       0x231dc protocol witness for KeyedDecodingContainerProtocol.decodeIfPresent<A>(_:forKey:) in conformance _JSONKeyedDecodingContainer<A> + 36
15 libswiftCore.dylib             0x67dbc _KeyedDecodingContainerBox.decodeIfPresent<A, B>(_:forKey:) + 520
16 libswiftCore.dylib             0x55880 KeyedDecodingContainer.decodeIfPresent<A>(_:forKey:) + 76
17 MyApp                          0x1648dc MyClass.TokenResponse.init(from:) + 4344695004 (<compiler-generated>:4344695004)
18 MyApp                          0x164a78 protocol witness for Decodable.init(from:) in conformance MyClass.TokenResponse + 4344695416 (<compiler-generated>:4344695416)
19 libswiftCore.dylib             0x34c124 dispatch thunk of Decodable.init(from:) + 32
20 libswiftFoundation.dylib       0x51380 specialized __JSONDecoder.unbox<A>(_:as:) + 2540
21 libswiftFoundation.dylib       0x21048 __JSONDecoder.unbox_(_:as:) + 424
22 libswiftFoundation.dylib       0xcfc4 JSONDecoder.decode<A>(_:from:) + 1548
23 libswiftFoundation.dylib       0x44fc4 dispatch thunk of JSONDecoder.decode<A>(_:from:) + 56
24 MyApp                          0x12b84c closure #1 in MyClass.GetAllServerTokens() + 188 (MyClass.swift:188)
25 MyApp                          0x12add0 thunk for @escaping @callee_guaranteed (@guaranteed Data?, @guaranteed NSURLResponse?, @guaranteed Error?) -> () + 4344458704 (<compiler-generated>:4344458704)
26 CFNetwork                      0x22b34 CFURLRequestSetMainDocumentURL + 3028
27 CFNetwork                      0x33af8 _CFNetworkErrorCopyLocalizedDescriptionWithHostname + 11412
28 libdispatch.dylib              0x2914 _dispatch_call_block_and_release + 32
29 libdispatch.dylib              0x4660 _dispatch_client_callout + 20
30 libdispatch.dylib              0xbde4 _dispatch_lane_serial_drain + 672
31 libdispatch.dylib              0xc98c _dispatch_lane_invoke + 444
32 libdispatch.dylib              0x171a8 _dispatch_workloop_worker_thread + 656
33 libsystem_pthread.dylib        0x10f4 _pthread_wqthread + 288
34 libsystem_pthread.dylib        0xe94 start_wqthread + 8

编辑:获取的 JSON 示例。出于安全考虑,我不能 post。它每 2 小时更改一次,因此我没有导致崩溃的确切副本,但它应该始终遵循此模式。 ticketsessionId 永远不会为空:

{
    "1": {
        "ticket":"aRandomJSONWebTokenHere",
        "expiration":"2022-01-16T10:00:38.2775891Z",
        "sessionId":"aUuidHere"
    },
    "2": {
        "ticket":"aRandomJSONWebTokenHere",
        "expiration":"2022-01-16T10:00:38.2775891Z",
        "sessionId":"aUuidHere"
    }...all the way until 60
}

编辑 2:self.dateFormatter

let dateFormatter : DateFormatter = {
    let df = DateFormatter()
    df.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"     
    return df
}()

self.dateFormatter 未修改。它以相同的方式在其他地方使用,作为 dateDecodingStrategy。也许当多个 URLSession 同时读取 self.dateFormatter 时会发生此崩溃?

Maybe this crash happens when more than one URLSession read self.dateFormatter at the same time?

当然,这是可能的。您的代码肯定是线程不安全的!但是很明显该怎么做;在您的 URLSession.shared.dataTask 完成处理程序中,进入主线程并停留在那里。

URLSession.shared.dataTask(with: urlRequest) { (data, res, err) in
    guard let data = data else { return }
    DispatchQueue.main.async {
        do { // ...
        }
        catch { // ...
        }
    }
}.resume()