目标 C:[MyObject alloc] 现在在 iOS SDK 4.1 下崩溃
Posted
技术标签:
【中文标题】目标 C:[MyObject alloc] 现在在 iOS SDK 4.1 下崩溃【英文标题】:Objective C: [MyObject alloc] now crashes under iOS SDK 4.1 【发布时间】:2010-09-16 09:30:40 【问题描述】:我正在处理现有的大型代码库,在将 ios SDK 升级到 4.1 后,我现在看到了非常奇怪的行为。问题的症结似乎是一个将不再分配的特定类——它在 obj_msgSend 中引发了错误的访问,并且似乎是 objc_msgSend 不喜欢的堆栈上的 Class 对象——尽管它实际上不是 NULL。
原来的失败行是这样的:-
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
在调试器中,看起来 Class 对象是合理的,但是 NSLog 在尝试打印它时崩溃。
需要注意的一点:有问题的类声明如下,我不确定协议是否导致问题。因为这个特定部分是一大块开源代码,所以很难删除这个协议要求,看看是否有什么不同。
@interface RMFractalTileProjection : NSObject<RMMercatorToTileProjection>
...
非常感谢您对此的任何帮助 - 这是一个表演终结者。
谢谢
【问题讨论】:
我应该指出,我尝试以这种方式获取课程,但它也崩溃了: Class c = [RMFractalTileProjection class]; 另外,我已经输入了一个方法来转储类内部,它看起来不错。但我不能分配它。这开始让我发疯了...... 【参考方案1】:这不是一个真正的答案,而是一些前进的想法。
目前想到的唯一原因是内存损坏和某种链接问题。也许您正在以某种方式链接该类的两个版本。
假设this 是类,让它在alloc 中崩溃似乎没有什么问题。没有 +initialize 或任何东西。
我会问自己并试图回答的问题是:
如果我重命名课程会发生什么?
如果我用不同的名称创建一个新的相同类会发生什么?
传递给 obj_msgSend 的指针:合理吗?它是否指向看起来像类的东西?
您是否曾经子类化该类并在子类上使用初始化?
指针总是一样的吗?如果是这样,您可以观察它所指向的内容,看看它在执行过程中是否发生了变化。
如果你把自己送到班级会发生什么?
【讨论】:
【参考方案2】:好的,终于找到了。正如 Jeremy 建议的那样,这被证明是一种常规的记忆障碍。
我发现它的困难在于,被踩踏的不是 Class 对象本身,而是类的元类结构——这是一个普通的 Class 对象,但上一层,由类“isa”指针引用.这就是为什么当我在调试器中检查该类时它看起来不错的原因——我需要跟踪 isa 指针并将内存转储到上一层才能找到它。对我来说幸运的是,这个类只是 NSObject 的一个子类——如果它被深度子类化,这可能会更难找到。在咬紧牙关、逆向工程 objc_msgSend、准确计算堆栈帧上的内容并遵循所有指针后,我得到了第一个线索。是的,艰难的方式:)
Matt Gallaghar's post(以及我通过以下链接找到的各种其他人)在帮助我通过这个迷宫方面非常宝贵 - 谢谢大家!
在这方面花了很多时间,但从好的方面来说,在过去的一天半里,我学到了很多关于 Objective C 内部原理的东西 :)
【讨论】:
是什么在内存中踩踏,导致类元数据被破坏?这似乎几乎是不可能的。【参考方案3】:感谢 JeremyP 的这些建议 - 在您整天敲打键盘之后,有新的建议总是好的!
您创建具有相同名称的相同类的建议似乎已经解决了这个问题。我不知道为什么,我觉得我需要了解这里发生了什么。没错,这听起来像是某种链接器问题,但我仍然不知道什么会导致如此严重的运行时错误,甚至在构建时都不会产生警告。
回复。指针,它看起来确实是合理的,但是类中的某些东西最终被取消引用为 objc_msgSend 中的空指针。有时,在我更改代码并重建后,我会得到一个空指针。这种行为显然暗示了一些不确定的东西,比如记忆力。
我会发布我的发现。
【讨论】:
这不应该作为另一个答案发布。这只是对 JeremyP 帖子的评论(尽管很长)。请记住,这是一个问答网站,而不是论坛。 是的,我深思熟虑过,但这有点像是一个答案(因为其中一个建议解决了问题),而且像这样没有换行符的长评论也很难读。跨度>以上是关于目标 C:[MyObject alloc] 现在在 iOS SDK 4.1 下崩溃的主要内容,如果未能解决你的问题,请参考以下文章
C++/Windows:如何报告内存不足异常(bad_alloc)?