目标 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 下崩溃的主要内容,如果未能解决你的问题,请参考以下文章

方便的构造函数 ARC 目标 c

C++/Windows:如何报告内存不足异常(bad_alloc)?

JNIEnv不能在其他c文件中调用方法?

Android ArrayList<MyObject> 作为 parcelable 传递

目标 c 中的保留概念

如何在 C 中调试 gdb 中的 St9bad_alloc 故障?