考虑这个代码:
static Nsstring *staticString = nil;int main (int argc,const char * argv[]) { NSautoreleasePool * pool = [[NSautoreleasePool alloc] init]; if (staticString == nil) { staticString = [[NSArray arrayWithObjects:@"1",@"2",@"3",nil] componentsJoinedByString:@","]; } [pool drain]; NSLog(@"static: %@",staticString); return 0;}
我期待这个代码崩溃.相反,它记录:
2011-01-18 14:41:06.311 EmptyFoundation[61419:a0f] static: static:
但是,如果我将NSLog()更改为:
NSLog(@"static: %s",[staticString UTF8String]);
然后它崩溃了.
编辑更多信息:
排水池后:
NSLog(@"static: %@",staticString); //this logs "static: static: "NSLog(@"static: %@",[staticString description]); //this crashes
所以显然在字符串上调用一个方法是足够好让它崩溃的.在这种情况下,为什么不记录字符串直接导致它崩溃? NSLog()是否应该调用-description方法?
第二个“静态”来自哪里?为什么这不会崩溃?
结果:
Kevin Ballard和Graham Lee都是正确的. Graham在意识到NSLog()并没有调用-description(正如我错误地假设)时是正确的,Kevin几乎绝对是正确的,这是一个复制格式字符串和va_List的一个奇怪的堆栈相关的问题.
> NSLogging和Nsstring不调用-description.格雷厄姆优雅地展现了这一点,如果你跟踪核心基金会的采伐记录,你会发现是这种情况. NSLog内部的任何回溯显示它调用NSLogv => _CFLogvEx => _CFStringCreateWithFormatandArgumentsAux => _CFStringAppendFormatandArgumentsAux. _CFStringAppendFormatAndArgumentsAux()
(第5365行)是所有魔法的地方.您可以看到手动通过以查找所有的%替换.如果替换的类型是CFFormatObjectType,描述函数不为零,并且替换尚未被另一个类型处理,则最终只会调用描述复制函数.由于我们已经表明该描述没有被复制,所以可以合理地假定Nsstring处理得更早(在这种情况下,它可能要做一个原始的字节副本),这导致我们相信…
>凯文推测,这里有一个堆栈错误.指向自动释放的字符串的指针被替换成一个不同的对象,这恰好是一个Nsstring.所以,它不会崩溃.奇怪的.但是,如果我们将静态变量的类型更改为其他类型,就像NSArray一样,则会调用-description方法,并且程序会按预期方式崩溃.
如何真正和完全陌生要点凯文是对行为根本原因的最正确的,并且对格雷厄姆的态度来纠正我的谬论.我希望能接受两个答案…
解决方法 我最了解您所看到的是NSLog()复制格式字符串(可能是可变副本),然后解析参数.因为你已经处理了staticString,所以这样就可以将格式化字符串的副本放在同一个位置.这将导致您看到您所描述的“static:static:”输出.当然,这个行为是未定义的 – 不能保证它总是使用相同的内存位置.另一方面,您的NSLog(@“static:%s”,[staticString UTF8String])在格式字符串复制发生之前正在访问staticString,这意味着它正在访问垃圾内存.
总结以上是内存溢出为你收集整理的objective-c – 为什么不会崩溃?全部内容,希望文章能够帮你解决objective-c – 为什么不会崩溃?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)