我在.m文件中声明了一个全局NSString变量。当我在.m文件中的任意位置使用stringWithFormat为其提供字符串值时,该值在两次函数调用之间不会持久存在。但是,当我使用stringWithString执行相同的操作时,该值在整个实现和任何函数调用中都保持不变,从而使其具有真正的全局行为。换句话说,stringWithFormat和stringWithString在内部的内存管理有什么不同?
当使用stringWithString时,为什么在抛出“消息发送到释放的实例”(在另一个函数中的NSLog语句中,该函数使用stringWithFormat为NSString赋值之后)抛出“消息发送到释放的实例”时,该值仍然存在?当我用stringWithString替换时,没有这样的问题。
谢谢!
编辑:我忘了提到,是的,在stringWithFormat的情况下,当我后来做了一个手动保留时,它是有效的。该值持续存在。这就是问题所在。
发布于 2011-02-22 20:04:00
编译器很聪明,他不是创建几十个不同的NSString实例,它们都具有相同的值,而是创建一个无法释放的实例,而所有其他实例只指向程序中硬编码的NSString。
因为硬编码的NSString永远不会被释放,所以即使在自动释放池已经释放了它之后,你也可以使用它。
这仅仅涵盖了你错误的内存管理。而且你绝对不应该依赖这种行为。
编辑。没什么可说的了。使用stringWithString: NSString创建的字符串将简单地指向文本在内存中的位置。
下面是一个小示例:
NSString *string = @"Foo";
NSLog(@"%@ - %p", string, string);
NSString *string2 = string;
NSLog(@"%@ - %p", string2, string2);
NSString *string3 = [string copy];
NSLog(@"%@ - %p", string3, string3);
NSString *string4 = [string retain];
NSLog(@"%@ - %p", string4, string4);
NSString *string5 = [NSString stringWithString:string];
NSLog(@"%@ - %p", string5, string5);
NSString *string6 = [[NSString alloc] initWithString:string];
NSLog(@"%@ - %p", string6, string6);您将看到它们都指向相同的地址。
2011-02-22 13:24:41.202 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.204 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.204 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.206 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.206 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.207 xxx[40783:207] Foo - 0x74120他们所有人都不会被取消分配。因此,您可以从代码中的其他方法访问string5,它仍然指向地址295740,并且NSString "Foo“仍然在那里。
但是没有指向字符串文字的NSString对象将在此时被释放,并且您将得到一个糟糕的访问异常。
您违反了内存管理规则,但是如果您只使用字符串文字,您将永远不会注意到这一点。直到编译器的行为改变。
所以做对了,学习适当的内存管理,不要依赖内部机制。如果以后需要,请保留所有自动释放的对象。即使它们指向字符串文字
发布于 2011-02-22 20:04:11
听起来你没有保留这个字符串,因此当你以后试图访问它的时候,它已经被释放了。如果你不熟悉内存管理,可以看看苹果的Memory Management Programming Guide。
-stringWithString:没有中断的原因很可能是因为编译器正在对字符串文字进行一些优化;它查看整个程序并只存储对定义的相同字符串的一个引用。因此,您的指针将在应用程序的整个生命周期中保持有效。
你不应该依赖这一点。你不能保证所有的编译器都会做这种优化。在创建变量时保留它,并在不再需要它时释放它。
https://stackoverflow.com/questions/5077678
复制相似问题