【问题标题】:How to Find the Source of an NSInternalInconsistencyException in an Xcode Stack Trace如何在 Xcode 堆栈跟踪中找到 NSInternalInconsistencyException 的来源
【发布时间】:2015-10-08 06:56:54
【问题描述】:

我正在使用 Objective-C 开发一个 iPhone 应用程序(使用 Xcode 6.1.1 和 Parse),我刚刚得到了这个神秘的 NSInternalInconsistencyException

Caught "NSInternalInconsistencyException" with reason "Tried to save an object with a pointer to a new, unsaved object.":

所以我对 Stack Overflow 社区的问题是:

有人如何阅读此堆栈跟踪以找出问题的实际根源?我在此堆栈跟踪中的任何位置都看不到任何可识别的文件名、方法调用或行号。

或者,如果这不是简单地读取堆栈跟踪的问题,并且涉及其他技术,那么开发人员应该采取什么适当的下一步来追踪此类错误的来源?

这是输出到我的控制台的完整堆栈跟踪:

2015-07-18 02:01:17.596 testapp [1276:60b] [错误]:捕获“NSInternalInconsistencyException”,原因是“尝试使用指向新的未保存对象的指针保存对象。”: ( 0 核心基础 0x2f547f9b + 154 1 libobjc.A.dylib 0x39c94ccf objc_exception_throw + 38 2 核心基础 0x2f547ec5 + 0 3 testapp 0x00205a29 -[PFObject(Private) resolveLocalId] + 384 4 testapp 0x00233d6d __32-[PFRESTCommand resolveLocalIds]_block_invoke + 24 5 testapp 0x00233783 +[PFRESTCommand forEachLocalIdIn:doBlock:] + 642 6 testapp 0x00233ba7 __42+[PFRESTCommand forEachLocalIdIn:doBlock:]_block_invoke + 62 7 核心基础 0x2f484043 + 98 8 核心基础 0x2f483f67 + 162 9 testapp 0x0023367f +[PFRESTCommand forEachLocalIdIn:doBlock:] + 382 10 testapp 0x00233ba7 __42+[PFRESTCommand forEachLocalIdIn:doBlock:]_block_invoke + 62 11 核心基础 0x2f484043 + 98 12 核心基础 0x2f483f67 + 162 13 testapp 0x0023367f +[PFRESTCommand forEachLocalIdIn:doBlock:] + 382 14 testapp 0x0023373f +[PFRESTCommand forEachLocalIdIn:doBlock:] + 574 15 testapp 0x00233ba7 __42+[PFRESTCommand forEachLocalIdIn:doBlock:]_block_invoke + 62 16 核心基础 0x2f484043 + 98 17 核心基础 0x2f483f67 + 162 18 testapp 0x0023367f +[PFRESTCommand forEachLocalIdIn:doBlock:] + 382 19 testapp 0x00233ca3 -[PFRESTCommand forEachLocalId:] + 162 20 testapp 0x00233d3f -[PFRESTCommand resolveLocalIds] + 34 21 测试应用程序 0x0023ee2f -[PFRESTCommandRunner _runCommandAsync:withCancellationToken:] + 110 22 测试应用程序 0x0023e8c7 -[PFRESTCommandRunner runCommandAsync:withOptions:cancellationToken:] + 174 23 测试应用程序 0x0023e7d7 -[PFRESTCommandRunner runCommandInBackground:inOperation:] + 42 24 testapp 0x00203667 __65+[PFObject(Private) _deepSaveAsync:withCurrentUser:sessionToken:]_block_invoke_3 + 766 25 testapp 0x002854b3 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke_2 + 214 26 libdispatch.dylib 0x3a17c833 + 10 27 libdispatch.dylib 0x3a183ad7 + 222 28 libdispatch.dylib 0x3a183d29 + 56 29 libsystem_pthread.dylib 0x3a2bebd3 _pthread_wqthread + 298 30 libsystem_pthread.dylib 0x3a2bea98 start_wqthread + 8 )。

感谢您为我提供的任何帮助和见解。

【问题讨论】:

    标签: ios objective-c xcode debugging stack-trace


    【解决方案1】:

    这个特殊的例子并没有给开发者太多的帮助。因此,在这种情况下,您的问题的答案是“Google it”。真的,堆栈跟踪中最好的线索是以下行:

    [PFObject(Private) _deepSaveAsync:withCurrentUser:sessionToken:]
    

    上面的行表示使用currentUser 保存失败,并结合错误消息“尝试使用指向新的未保存对象的指针保存对象”。应该足以指出可能的原因。

    事实证明,这个错误并不少见,并且令人困惑为什么 Parse 不修复它。这通常是由于您的应用程序使用匿名 Parse 用户并在保存用户对象之前尝试保存对象而引起的。由于用户对象没有保存,所以没有objectId,其他对象保存失败。

    解决方案是检查currentUser 对象是否有objectId,如果没有,请先保存,然后再尝试写入 Parse。

        // Prevent race condition for unsaved user
        // Courtesy of: http://samwize.com/2014/07/15/pitfall-with-using-anonymous-user-in-parse/
        if ([PFUser currentUser].objectId == nil) {
            [[PFUser currentUser] saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
                //do stuff later
            }];
        } else {
            //do stuff now
        }
    

    【讨论】:

    • 谢谢。这确实帮助我朝着正确的方向前进。
    【解决方案2】:

    NSInternalInconsistencyException 在代码进入不应该发生的状态时抛出。通常它表示编写它的人犯了一个错误,尽管有时可能通过滥用库(例如,对文档所说的做一些事情)而导致这种情况。

    换句话说,这是一个错误,但如果你没有编写抛出它的代码,它可能不是你的。从这个特定的堆栈跟踪中,问题必须在 Parse 中。

    将错误报告给原始开发人员。一个好的库决不能扔掉它,不管你是否滥用它。在他们修复它之前,你能做的最好的事情就是尝试解决它,通过以不同的方式做你想做的事情。如果您有该库的来源,您可以尝试自己调试和修复问题。

    【讨论】:

    • 感谢您的回答,尽管我仍然需要知道如何阅读此堆栈跟踪以找到有问题的区域(在我的代码或解析中)以遵循您的建议,例如 "doing what you正在尝试以不同的方式做”(我怎么知道在不知道原因的情况下要做什么不同的事情?),或者 “如果你有那个库的源代码,你可以尝试调试和修复自己的问题”(我怎么知道如何找到正确的代码来修复?)。我的问题实际上是关于“采取哪些步骤来查找此错误的根源”,然后从那里,我可以听从您的建议。再次感谢。
    • @IchigoKurosaki 想到的唯一“步骤”是重新符号化堆栈跟踪(例如使用atos 工具)以获取每个帧的源文件名和行号。我认为除此之外不会有任何非特定步骤,因为您的问题实际上与“如果我有错误,我该如何找到它?”一样笼统。
    • 感谢您的建议,但我觉得我的问题比“如果我有错误,我如何找到它?”要具体得多,因为我在问“如果我有堆栈跟踪,我怎么读?”。您建议的第一部分是使用 atos 工具重新符号化,这听起来很有帮助。您能否发布一些有关某人如何使用此工具从堆栈跟踪中获取更多[可读]细节的详细信息的答案?因为这样的答案会让人觉得与问题相关。任何帮助表示赞赏。
    • 我也对如何阅读堆栈跟踪感兴趣。看了很多资料,还是找不到好的答案。如何准确找到导致崩溃的那行代码?是否可以通过堆栈跟踪行中的哈希值找到它?有人可以解释一下吗))
    【解决方案3】:

    当你看到这样的错误并且 Xcode 将你踢到 AppDelegate 时,尝试在 Xcode 2 中设置断点

    • Swift 错误断点
    • 异常断点...

    您将在顶部的左侧面板中找到这些选项

    Breakpoint Navigator -> +(这个符号位于底部)-> Swift 错误断点或/和异常断点

    希望下次能帮到你

    【讨论】:

      猜你喜欢
      • 2010-10-31
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-02
      • 2020-10-25
      • 1970-01-01
      相关资源
      最近更新 更多