【问题标题】:Bad memory alignment iOS糟糕的内存对齐iOS
【发布时间】:2013-09-13 06:49:43
【问题描述】:

我被以下崩溃报告卡住了:

Date/Time:       2013-09-12 22:39:54 +0000
OS Version:      iPhone OS 6.1.3 (10B329)
Report Version:  104

Exception Type:  SIGSEGV
Exception Codes: SEGV_ACCERR at 0xa0000008
Crashed Thread:  0

Thread 0 Crashed:
0   libobjc.A.dylib                     0x39a3c564 _cache_getImp + 4
1   libobjc.A.dylib                     0x39a3e1d7 class_respondsToSelector + 31
2   CoreFoundation                      0x31b96605 objectIsKindOfClass + 37
3   CoreFoundation                      0x31b9635d __handleUncaughtException + 69
4   libobjc.A.dylib                     0x39a41a65 _objc_terminate() + 129
5   libc++abi.dylib                     0x3948e07b safe_handler_caller(void (*)()) + 79
6   libc++abi.dylib                     0x3948e114 std::terminate() + 20
7   libc++abi.dylib                     0x3948f599 __cxa_current_exception_type + 1
8   libobjc.A.dylib                     0x39a419d1 objc_exception_rethrow + 13
9   CoreFoundation                      0x31adcf21 CFRunLoopRunSpecific + 457
10  CoreFoundation                      0x31adcd49 CFRunLoopRunInMode + 105
11  GraphicsServices                    0x356a82eb GSEventRunModal + 75
12  UIKit                               0x339f2301 UIApplicationMain + 1121
13  Our App                             0x0003bc27 main (main.m:15)

在多次尝试修复导致此错误的错误后,我不断从 PLCrashReporter(来自我们的 beta 测试人员的临时构建)收到此崩溃日志。不同的异常代码从 SIGSEGV/SEGV_ACCERR 到 SIGBUS/BUS_ADRALN 再到 EXC_BAD_ACCESS/KERN_INVALID_ADDRESS

我在 iOS(armv7 和 armv7s)上使用 rapidjson libraryhere (#8) 所述的填充修复,我使用 Objective-c 运行时函数在运行时添加方法实现(使用 class_addMethod)。

我们的代码库大部分是 Objective-C 代码,一些 Obj-C++ 和一些 C 代码。内存管理由 ARC 完成,但 Obj-C++ 和 C 部分是手动处理的。我查看了每个 malloc/free 调用,并广泛使用 libgmalloc 来确定内存问题,但没有什么对我来说不正确。

我自己无法重现此崩溃日志,而不是在调试或发布模式下,但我们的 Beta 测试人员会不时向我发送此崩溃日志(大约 50 次运行中有 1 次)。由于我们的产品(希望)很快就会在许多 iOS 设备上运行,所以我们不能让这件事被破坏。

在阅读了很多内存管理文章后,我怀疑这个问题是由于内存对齐错误造成的。因此我怀疑 rapidjson 是这个错误的原因。我对 iOS / armv7 上的内存对齐缺乏了解,因此无法修复此崩溃日志。有人可以在 iOS 上向我解释更多关于这个主题的信息吗?还是我找错地方了,这是另一个内存问题吗? 我希望有人能指出我正确的方向。

如果需要更多信息,我很乐意提供。 注意:我不是在寻找使用 JSONKit 或其他库来替换 rapidjson 的答案。谢谢:)

【问题讨论】:

    标签: ios objective-c runtime rapidjson


    【解决方案1】:

    此问题之前已在此处解决:https://devforums.apple.com/message/807860

    简而言之,原始的 Objective-C 异常在未捕获的异常处理程序中被取消引用之前已被释放(例如,通过自动释放池)。因此, __handleUncaughtException() 取消引用一个现已失效的指针,您会在异常处理程序中看到崩溃。

    【讨论】:

    • 非常感谢,这确实是原因。我完全在错误的轨道上寻找错误。我现在可以在调试器中重现此错误 :)
    【解决方案2】:

    首先,地址0xa0000008看起来并没有错位,SEGV_ACCERR也不是对齐问题,而是内存访问权限问题(来自sys/signal.h):

    #define SEGV_ACCERR     2       /* [XSI] invalid permission for mapped object */
    

    考虑到您正在使用 class_addMethod() 并且崩溃发生在 _cache_getImp() 中,这是检索方法的一部分,我在很大程度上没有根据的怀疑是您传递了一些无效指针到 class_addMethod(),或者稍后覆盖了该信息.

    需要检查的是您使用的是全局内存还是 malloc()ed 内存,因为运行时函数不会为您制作副本。

    其次,您看到的崩溃是次要的,您在运行顶级异常处理程序时崩溃了(_objc_terminate())您的程序已经从较早的异常中终止,但在这种情况下它不是 Unix 信号,但是一个 Objective-C 异常:objc_exception_rethrow()

    因此,您可能需要首先找出主要错误,例如从异常日志中找出(在很多情况下,仅回溯是不够的)。

    【讨论】:

    • 感谢您的提示,我会调查的。同时,您对如何检索异常日志有什么建议吗?我应该使用自己的 uncaughtException 而不是 PLCrashReporter 吗? NSException 对象的哪些属性应该包含所需的信息?
    • 看起来二次崩溃实际上可能在 PLCrashReporter 中。您是否尝试过将其删除?
    • PLCrashReporter 在给定的回溯中不可见;此问题发生在 PLCrashReporter 参与之前。
    猜你喜欢
    • 2014-03-02
    • 2014-06-30
    • 2014-09-07
    • 2013-11-14
    • 2013-11-08
    • 2011-09-13
    • 2014-11-18
    • 2022-07-13
    • 2018-08-15
    相关资源
    最近更新 更多