目标C:[MyObject Alloc]现在在iOS SDK 4.1下崩溃
-
03-10-2019 - |
题
我正在研究现有的大型代码库,然后将iOS SDK升级到4.1后,我现在看到了非常奇怪的行为。此事的关键似乎是不再会出现的特定类 - 它在OBJ_MSGSEND中抛出了不良访问,并且似乎是OBJC_MSGSEND不喜欢的堆栈中的类对象 - 尽管实际上并非无效。
原始的失败线看起来像这样: -
tileProjection = [[RMFractalTileProjection alloc] initFromProjection:proj tileSideLength:sideLength maxZoom:18];
我对此进行了解构以隔离问题: -
RMFractalTileProjection *p = [RMFractalTileProjection alloc]; // <- this crashes
p = [p initFromProjection:proj tileSideLength:sideLength maxZoom:18];
tileProjection = p;
然后,我尝试了: -
Class c = NSClassFromString(@"RMFractalTileProjection");
assert(c);
NSLog( @"RMFractalTileProjection class(ptr) %p", c ); // <- prints an address OK
NSLog( @"RMFractalTileProjection class(obj) %@", c ); // <- crashes
在调试器中,看起来类对象是明智的,但是NSlog试图打印它时会崩溃。
要注意的一件事:所讨论的课程如下所示,我不确定协议是否引起问题。由于该特定部分是开源代码的很大一部分,因此很难删除此协议要求以查看是否有所作为。
@interface RMFractalTileProjection : NSObject<RMMercatorToTileProjection>
{
...
}
对此的任何帮助都非常感谢 - 这是表演的阻止者。
谢谢
解决方案 2
好的,终于找到了这个。正如杰里米(Jeremy)所建议的那样,事实证明这是一个常规的记忆力。
我发现的困难是,这不是踩踏的类对象本身,而是类的“元组结构” - 这是一个普通的类对象,但是一个级别,由“ ISA”指针引用。这就是为什么当我在调试器中检查它时,这堂课对我来说还不错 - 我需要按照ISA指针和一个级别的转储记忆来找到这个。对我来说幸运的是,这堂课只是nsobject的一个子类 - 如果它被深入分类,这可能很难找到。咬了子弹后,我得到了我的第一个线索,反向工程objc_msgsend,确切地弄清了堆栈框架上的内容,并遵循所有指针。是的,艰难的方式:)
马特·加拉拉格(Matt Gallaghar)的帖子 (以及我通过以下链接发现的其他各种)在帮助我度过这个迷宫方面非常宝贵 - 谢谢大家!
在这一段时间里烧毁了很多时间,但是在上一侧,我在过去的一天半中学到了很多关于目标C的内部群体的地狱:)
其他提示
这并不是真正的答案,而是一些前进的想法。
目前,唯一跳动的原因是内存腐败和某种链接问题。也许您正在以某种方式链接两个班级的版本。
假设 这 是课程,使其在Alloc中崩溃并没有什么错。没有 +初始化或任何东西。
我要问自己并试图回答的问题是:
如果我重命名班级会怎样?
如果我创建一个具有不同名称的新相同类,会发生什么?
传递给OBJ_MSGSEND的指针:合理吗?它指向看起来像课堂的东西吗?
您是否曾经为课程子类,并在子类上使用初始化吗?
指针总是一样吗?如果是这样,您可以观察指向的内容,并查看执行过程中是否更改。
如果您将自己送入班级会怎样?
感谢这些建议 - 耶利目的地 - 在整天将头撞到键盘上后,最好有新的建议!
您的建议创建一个具有相同名称的相同课程 出现 解决问题。我不知道为什么,我觉得我需要理解这里发生了什么。您是对的,听起来像是某种链接器问题,但是我仍然不知道是什么可能导致如此严重的运行时错误,甚至在构建时间都没有发出警告。
关于。指针看起来确实合理,但是班级内部的某些内容最终被视为OBJC_MSGSEND内部的无效指针。有时,在我更改代码并重建后,我会得到一个无效的指针。这种行为显然暗示了不确定的东西,例如记忆踩踏。
我会发布我的发现。