gpt4 book ai didi

ios - 堆栈溢出 : Thread 1: EXC_BAD_ACCESS (code=2, 地址=0x16d09aa00)

转载 作者:行者123 更新时间:2023-12-03 11:16:06 25 4
gpt4 key购买 nike

崩溃描述
最近,我在我的一个 iOS/Swift 项目中遇到了非常奇怪的内存问题。我真的不确定发生了什么,感觉也不太容易描述,但无论如何我会尽力而为。
它的行为基本上如下:

  • 在某个代码库上,崩溃总是发生在同一个地方(100% 可重现)
  • 对代码库的更改可能会解决问题,但它也可能只是在其他地方弹出
  • 崩溃只发生在真实设备上,从不在模拟器内

  • 目前该应用程序因以下错误而崩溃(3 次不同运行的结果):

    Thread 1: EXC_BAD_ACCESS (code=2, address=0x16d09aa00)

    Thread 1: EXC_BAD_ACCESS (code=2, address=0x16af46a00)

    Thread 1: EXC_BAD_ACCESS (code=2, address=0x16d526a00)



    关于内存地址的推理
    WWDC session
    我从 WWDC 2018 中发现了一个有趣的 session ( Understanding Crashes and Crash Logs),其中一个人指出,有时可以从特定的内存地址中获取更多信息,从而发生崩溃。
    不幸的是,它在我的应用程序中崩溃的地址有些完全不同,但也许我们可以从它们那里得到线索?至少有趣的是,它们都非常相似,不是吗?
    由于启用了诊断选项而导致的更改
    进一步调查表明,前 2 个字节 (16) 始终保持不变,然后是 4 个随机字节,然后是 3 个字节 (a00)。激活诊断(例如 ASan 或 Scribble)时,最后 3 个字节会发生变化(例如 3a0 或 9e0)。但也许这只是由于添加了更多“调试内容”而导致的一种转变?我真的不是那个“内存人”,但只想提供我注意到的任何东西。

    尝试“诊断选项”
    我尝试了不同的诊断选项(来自方案),但它们都没有真正以任何方式改变崩溃,也没有提供更多信息。
    1. 涂鸦
    崩溃不引用 0xAA 或 0x55,所以使用 Scribble 没有什么可以捕获的? ( Xcode - scribble, guard edges and guard malloc)
    2. Malloc 保护边缘
    使用它也没有注意到任何区别。
    3.僵尸
    使用这个 guide . malloc_info --type 0x16b15e9c0

    error: error: Trying to put the stack in unreadable memory at: 0x16b15e920.


    4.阿桑
    使用 ASan 只需将以下条目放在堆栈跟踪的顶部。不幸的是,我没有发现任何与此相关的有用信息。 #0 0x0000000109efbf60 in __asan_alloca_poison ()5. 桑
    在真实设备上不可用(崩溃只发生在那里)

    递归/BOF?
    可能是递归太长,还是另一种堆栈/堆缓冲区溢出?
    但似乎真实设备和模拟器上的堆栈大小与 524288 完全相同字节(来自 Thread.main.stackSize)。
    那么,由于它不会在模拟器中崩溃,所以它不是 BOF?还是架构差异太大,无法在这里得出这样的结论?

    拆卸
    我也尝试过“拆卸”。 disassemble -a 0x16d09aa00

    error: Could not find function bounds for address 0x16d09aa00


    disassemble -frame但是我的汇编技能真的很落后,所以目前我无法从这些信息中得到任何信息。

    需要帮忙
    如您所见,我真的没有想法了。要么崩溃真的很奇怪,要么我没有足够的知识/技能来使用上述工具,让我更接近这些问题的原因。
    无论哪种方式......任何帮助,提示,想法或任何可以指出我正确方向的东西都非常感谢!
    提前谢谢各位。

    2020 年 5 月 19 日更新
    我完全忘了提,我们正在使用 ReSwift在我们的应用程序中,崩溃似乎与我们在那里使用中间件的方式有关,我猜。
    我也已经与那里的开发人员取得了联系: github.com/ReSwift/ReSwift/issues/271 .
    最后是一些代码。不幸的是,我不能分享所有的应用程序代码(这可能是必要的!?),也不想让你用太多的代码来重载你。
    目前的问题

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


    UserAccountMiddleware.swift
    注意:使用那些 DispatchQueue.main.async实际上使崩溃消失了。他们确实打破了当前的循环,所以也许发生了某种递归或时间问题?
    func userAccountMiddleware() -> Middleware<AppState> {
    return { dispatch, getState in
    return { next in
    return { action in
    switch action {
    case _ as ReSwiftInit:
    // DispatchQueue.main.async {
    dispatch(UserAccountSetAuthToken(authToken: Defaults.customerAuthToken))
    dispatch(UserAccountSetAvatar(index: Defaults.avatarIndex))
    // }
    if let data = Defaults.customer,
    let customer = try? JSONDecoder().decode(Customer.self, from: data) {
    // DispatchQueue.main.async {
    dispatch(UserAccountSetCustomerLoggedIn(customer: customer))
    // }
    }

    // [...]

    default:
    break
    }

    next(action)
    }
    }
    }
    }
    ReSwift Store.swift
        // [...]
    open func _defaultDispatch(action: Action) {
    guard !isDispatching else {
    raiseFatalError(
    "ReSwift:ConcurrentMutationError- Action has been dispatched while" +
    " a previous action is action is being processed. A reducer" +
    " is dispatching an action, or ReSwift is used in a concurrent context" +
    " (e.g. from multiple threads)."
    )
    }

    isDispatching = true
    let newState = reducer(action, state) // Thread 1: EXC_BAD_ACCESS (code=1, address=0x16ed82da0)
    isDispatching = false

    state = newState
    }
    // [...]
    Xcode 控制台:
    (lldb) po state
    error: warning: couldn't get required object pointer (substituting NULL): Couldn't load 'self' because its value couldn't be evaluated

    error: Trying to put the stack in unreadable memory at: 0x16d95ad00.
    汇编程序(崩溃的最后一步):
    myapp`type metadata accessor for GlobalState:
    0x101f6ac10 <+0>: sub sp, sp, #0x30 ; =0x30
    -> 0x101f6ac14 <+4>: stp x29, x30, [sp, #0x20] // Thread 1: EXC_BAD_ACCESS (code=1, address=0x16ed82da0)
    0x101f6ac18 <+8>: adrp x8, 3620
    0x101f6ac1c <+12>: add x8, x8, #0x148 ; =0x148
    0x101f6ac20 <+16>: ldr x8, [x8]
    0x101f6ac24 <+20>: mov x9, #0x0
    0x101f6ac28 <+24>: mov x1, x8
    0x101f6ac2c <+28>: str x0, [sp, #0x18]
    0x101f6ac30 <+32>: str x1, [sp, #0x10]
    0x101f6ac34 <+36>: str x9, [sp, #0x8]
    0x101f6ac38 <+40>: cbnz x8, 0x101f6ac54 ; <+68> at <compiler-generated>
    0x101f6ac3c <+44>: adrp x1, 2122
    0x101f6ac40 <+48>: add x1, x1, #0x1dc ; =0x1dc
    0x101f6ac44 <+52>: ldr x0, [sp, #0x18]
    0x101f6ac48 <+56>: bl 0x102775358 ; symbol stub for: swift_getSingletonMetadata
    0x101f6ac4c <+60>: str x0, [sp, #0x10]
    0x101f6ac50 <+64>: str x1, [sp, #0x8]
    0x101f6ac54 <+68>: ldr x0, [sp, #0x8]
    0x101f6ac58 <+72>: ldr x1, [sp, #0x10]
    0x101f6ac5c <+76>: str x0, [sp]
    0x101f6ac60 <+80>: mov x0, x1
    0x101f6ac64 <+84>: ldr x1, [sp]
    0x101f6ac68 <+88>: ldp x29, x30, [sp, #0x20]
    0x101f6ac6c <+92>: add sp, sp, #0x30 ; =0x30
    0x101f6ac70 <+96>: ret

    最佳答案

    TL;博士
    只需将巨大的结构移动到堆中,将它们包装在数组中即可。使用@propertyWrappers,这可能是一个至少部分优雅的解决方案。

    @propertyWrapper
    struct StoredOnHeap<T> {
    private var value: [T]

    init(wrappedValue: T) {
    self.value = [wrappedValue]
    }

    var wrappedValue: T {
    get {
    return self.value[0]
    }

    set {
    self.value[0] = newValue
    }
    }
    }

    // Usage:
    @StoredOnHeap var hugeStruct: HugeStruct
    https://gist.github.com/d4rkd3v1l/ab582a7cafd3a8b8c164c8541a3eef96

    长版
    我现在几乎 100% 确定这是堆栈溢出,因为我(最终)设法在一个小演示项目中重现了这一点: https://github.com/d4rkd3v1l/ReSwift-StackOverflowDemo
    现在,我将为可能遇到此问题或类似问题的其他人提供更多详细信息和解决方案。
    iOS 上的堆栈大小(截至 iOS 13)为 512kb,应适用于设备和模拟器。为什么我说“应该”?因为它几乎可以肯定在模拟器上有所不同,因为我没有看到那些崩溃。所以也许 Thread.main.stackSize只是告诉 512kb 但实际上更大? IDK🤷‍♂️

    以下是一些指标,您可能会遇到同样的问题:
  • 你得到 EXC_BAD_ACCESS使用代码 1 或 2** 崩溃。 崩溃发生在高内存地址中,或者至少完全不在您的应用程序/堆栈的其余部分通常“存在”的位置。像 0x16d95ad00就我而言。
  • 减少你放在堆栈上的东西(值类型,例如非常非常大的结构)或将调用堆栈分解成更小的部分(例如调度异步)以给堆栈一些“喘息时间”来防止这种崩溃。

  • 在后者,我们已经处于该问题的解决方案的中间。由于堆栈大小不能(甚至可能不应该)增加,因此您必须减少放在那里的负载,如第二点所述。
    至少这是我们可能会采用的解决方案。 🤞

    *至少对于主线程是这样,其他线程可能不同。
    **我认为代码 0 有点空指针异常,因此不适用于此处。如果我对此有误,请纠正我。

    关于ios - 堆栈溢出 : Thread 1: EXC_BAD_ACCESS (code=2, 地址=0x16d09aa00),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61793803/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com