目标C:[MyObject alloc]现在在iOS SDK 4.1下崩溃了

时间:2010-09-16 09:30:40

标签: iphone objective-c ios alloc

我正在开发一个现有的大型代码库,在将iOS SDK升级到4.1之后,我现在看到了非常奇怪的行为。而问题的关键似乎是,将不再页头一类特殊 - 它被扔在obj_msgSend不好的访问,似乎是在堆栈上的类对象objc_msgSend不喜欢 - 虽然它实际上不是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>
{
 ...
}

对此人的任何帮助都非常感激 - 这是一个表演者。

由于

3 个答案:

答案 0 :(得分:1)

这不是一个真正的答案,而是一些前进的想法。

目前跳跃到脑海的唯一原因是内存损坏和某种链接问题。也许你正在以某种方式链接该类的两个版本。

假设this是类,那么在alloc中使它崩溃似乎没有任何错误。没有+初始化或任何东西。

我会问自己并试图回答的问题是:

如果我重命名该课程会怎样?

如果我创建一个具有不同名称的新相同类会怎样?

传递给obj_msgSend的指针:是否合理?它是否指向看起来像一个类的东西?

你是否曾经继承过类,你是否在子类上使用了初始化?

指针总是一样吗?如果是这样,您可以观察它指向的内容并查看它是否在执行期间发生变化。

如果你自己上课,会发生什么?

答案 1 :(得分:1)

好的,终于找到了这个。正如杰里米建议的那样,事实证明这是一个常规的记忆障碍。

我发现它的难点在于它不是Class对象本身被踩,而是类'元类结构 - 这是一个普通的Class对象,但是一级,由类'isa'指针引用。这就是为什么当我在调试器中检查它时,该类看起来没问题 - 我需要按照isa指针并在一个级别转储内存以找到它。对我来说幸运的是,这个类只是NSObject的一个子类 - 如果它被深度子类化,那么这可能更难找到。咬住子弹后,我得到了我的第一个线索,逆向工程objc_msgSend,准确计算出堆栈帧上的内容,并遵循所有指针。是的,艰难的方式:)

Matt Gallaghar's post(以及我通过以下链接发现的各种其他内容)对于帮助我度过这个迷宫非常宝贵 - 谢谢你们!

在这个问题上花了很多时间,但是在过去的一天半里,我在Objective C内部学到了很多东西:)

答案 2 :(得分:0)

感谢JeremyP提出的这些建议 - 在你整天敲击键盘之后总是提出新的建议总是好的!

您建议使用相同名称​​创建相同的类以解决问题。我不知道为什么,我觉得我需要了解这里发生了什么。你是对的,听起来像某种链接器问题,但我仍然不知道什么可能导致如此严重的运行时错误,甚至不会在构建时产生警告。

重新。指针,它看起来确实合理,但类中的某些内容最终会被取消引用为objc_msgSend中的空指针。偶尔,在我更改代码并重建之后,我得到一个空指针。这种行为显然表明了像记忆踩踏一样不确定的东西。

我会发布我的发现。