我正在研究现有的大型代码库,然后将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内部的无效指针。有时,在我更改代码并重建后,我会得到一个无效的指针。这种行为显然暗示了不确定的东西,例如记忆踩踏。

我会发布我的发现。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top