我在.m文件中声明了一个全局NSString变量。当我使用stringWithFormat在.m文件中的任何位置给它一个字符串值时,该值不会在函数调用之间持续存在。但是当我使用stringWithString执行相同操作时,该值会在整个实现过程中持续存在,并且任何函数调用都会为其提供真正的全局行为。相反,换句话说,stringWithFormat vs stringWithString的内存管理有何不同?
为什么在抛出“发送到解除分配的实例的消息”时,stringWithString的值仍然存在(在NSString的后续使用中,在另一个函数中的NSLog语句中,在使用stringWithFormat为NSString赋值的函数之后)使用stringWithFormat?当我用stringWithString替换它时没有这样的问题。
谢谢!
编辑:我忘了提及是的,在stringWithFormat的情况下,当我之后进行手动保留时,它是有效的。价值持续存在。因此问题。
答案 0 :(得分:3)
听起来你没有保留字符串,因此当你试图访问它时,它已被解除分配。如果您不熟悉内存管理,请查看Apple的Memory Management Programming Guide。
-stringWithString:
不会中断的原因可能是因为编译器正在使用字符串文字进行一些优化;它查看程序并仅存储对已定义的相同字符串的一个引用。因此,您的指针在应用程序的整个生命周期内都将保持有效。
你不应该依赖于此。您不能保证所有编译器都会进行此优化。在制作变量时保留变量,并在需要时释放变量。
答案 1 :(得分:2)
编译器是智能的,而不是创建几个都保持相同值的不同NSString实例,而是创建一个无法释放的实例,而所有其他实例只指向程序中硬编码的NSString。
因为硬编码的NSString永远不会被释放,所以即使自动释放池已经解除分配,也可以使用它。
这只是涵盖了错误的内存管理。你绝对不应该依赖这种行为。
编辑。没有更多的话要说。您使用stringWithString:literal创建的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对象,您将获得错误的访问异常。
您违反了内存管理规则,但如果您只使用字符串文字,则永远不会注意到它。直到编译器的行为发生变化。
所以做得对,学习适当的内存管理,不要依赖内部。如果以后需要,请保留所有自动释放的对象。即使他们指向字符串文字