我正在开发一个现有的大型代码库,在将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>
{
...
}
对此人的任何帮助都非常感激 - 这是一个表演者。
由于
答案 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中的空指针。偶尔,在我更改代码并重建之后,我得到一个空指针。这种行为显然表明了像记忆踩踏一样不确定的东西。
我会发布我的发现。