【问题标题】:What is "super" in Objective-C? ( self != super )?Objective-C 中的“超级”是什么? (自我!=超级)?
【发布时间】:2012-04-01 02:54:17
【问题描述】:

我已经阅读了下面的问题,故事看起来很简单:

What exactly is super in Objective-C?

然而……

- (id) init
{
    NSLog(@"self=%p, super=%p", self, super);
}

打印出“self=0xa83dc50, super=0xbfffe8d0”。地址不一样???!?!?

第二个地址似乎是一个“特殊值”或其他东西。什么意思?

感谢 bbum 指出这个值是编译器用来实现“超级”行为的特殊结构的堆栈地址。


我可以调用 [super init] 并且调用似乎有效,或者至少没有爆炸……不会立即爆炸。调用 [((id)0xbfffe8d0) init] 因 EXC_BAD_ACCESS 而失败。

然后是真正奇怪的部分..... 我有一段代码无缘无故抛出“NSGenericException:集合在被枚举时发生了变异”异常。在 DIFFERENT 对象(基本上是具有指向 NSEnumerator 的指针的包装器)内,注释掉对“[super init]”的调用会导致异常不会发生。如果可以的话,我会奖励 $$$ 来回答那个令人费解的问题。

"id sups = (id)0xbfffe8d0" ...这也会导致“集合被修改”。 ... 怎么回事?好的,所以我要针对这种怪异的问题发布第二个问题......


我最初是带着其中一个“奇怪的症状”错误来到这里的,结果证明这是完全不相关的(典型的此类事情):Does casting an address to (id) have side-effects??? Is Address 0xbfffe8d0 special? (fixed: issue was with _NSCallStackArray)

但是,行上面的内容仍然有效,并且响应仍然很好。如果您想更深入地了解 ObjC,请阅读它。

【问题讨论】:

  • 除了你的其他问题,0xbfffe8d0 大概是一个代码地址,但没有理由期望它从一个编译到下一个编译都是一样的。将该文字值转换为指针基本上只是从随机数创建一个指针。
  • 其实是栈地址,和代码地址不是一回事。从一个运行到下一个运行甚至都不一样!
  • 在同一次运行中,堆栈地址从一个瞬间到下一个瞬间都不相同。

标签: iphone objective-c ios macos


【解决方案1】:

你在惹窗帘后面的人,他正在为此惩罚你...... :)

super 确实有点编译器的魔力。当您说[super doSomething] 时,编译器将发出对objc_msgSendSuper() 的调用,而不是objc_msgSend()。大多数时候——有一些特殊情况。

一般情况下,您应该将super 视为只是方法调用的目标。它不应该存储在任何地方,也不应该被视为除了用于消息传递的目标表达式。

事实上,涉及存储的super 的使用很可能会被编译器标记出来。

就您的错误而言,这听起来很像内存损坏、过度释放和/或并发发生。您需要提供更多与枚举相关的代码和其他相关代码以进一步推断。

【讨论】:

  • 嘿,“惹恼了幕后的人”:) 我发布了第二个问题,其中包含有关该错误的更多详细信息。
  • 如果您有兴趣,super 被实现(或曾经是)作为指向结构的指针。该结构包含两个元素,第一个是self,第二个是超类,它告诉运行时从哪个类开始查找。
  • 啊!这就解释了奇怪的价值。这是你提到的那个时髦结构的堆栈地址。
  • 是的;如果您要查看程序集,编译器会放置所述结构,然后objc_msgSendSuper() 使用superclassisa 开始方法搜索,同时使用结构对self 的引用作为方法的目标称呼。一个实现细节(感谢@ughoavgfhw 去那里!!)。
猜你喜欢
  • 2011-10-07
  • 2022-01-19
  • 2012-02-22
  • 1970-01-01
  • 1970-01-01
  • 2014-04-28
  • 1970-01-01
相关资源
最近更新 更多