objective-c – 为什么不会崩溃?

前端之家收集整理的这篇文章主要介绍了objective-c – 为什么不会崩溃?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图将一个错误缩小到最小可重复的情况,发现了一些奇怪的事情.

考虑这个代码

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,这意味着它正在访问垃圾内存.

猜你在找的C&C++相关文章