NSString - stringWithFormat 与 stringWithString

发布于 2024-10-18 21:51:29 字数 499 浏览 8 评论 0原文

我在 .m 文件中声明了一个全局 NSString 变量。当我使用 stringWithFormat 在 .m 文件中的任何位置为其提供字符串值时,该值不会在函数调用之间保留。然而,当我使用 stringWithString 执行相同操作时,该值在整个实现和任何函数调用中都保持不变,从而赋予它真正的全局行为。换句话说,stringWithFormat 与 stringWithString 的内存管理在内部有何不同?

使用 stringWithFormat 时,为什么 stringWithString 的值会持续存在,同时抛出“发送到已释放实例的消息”(在后续使用 NSString 时,在另一个函数的 NSLog 语句中说,该函数位于使用 stringWithFormat 为 NSString 提供值的函数之后)?当我用 stringWithString 替换它时没有这样的问题。

谢谢!

编辑:我忘了提及,是的,当我事后进行手动保留时,它在 stringWithFormat 的情况下起作用。价值依然存在。因此就有了这个问题。

I have a global NSString variable declared in a .m file. When I use the stringWithFormat to give it a string value anywhere within the .m file, that value does not persist in between function calls. However when I do the same using stringWithString, the value persists throughout the implementation and any functions calls thus giving it a true global behavior. Rather to put it differently, how does the memory management differ internally for stringWithFormat vs stringWithString?

Why does the value persist for stringWithString while throwing a "message sent to deallocated instance" (on subsequent use of the NSString say in a NSLog statement in another function which comes after a function that gave the NSString a value using stringWithFormat) when using stringWithFormat? No such issues when I replace the same with stringWithString.

Thanks!

EDIT: I forgot to mention that YES it worked in case of stringWithFormat when I did a manual retain afterward. The value persisted. Hence the question.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

々眼睛长脚气 2024-10-25 21:51:29

听起来您没有保留该字符串,因此当您稍后尝试访问它时,它已被释放。如果您不熟悉内存管理,请查看 Apple 的内存管理编程指南

-stringWithString: 没有中断的原因可能是因为编译器正在对字符串文字进行一些优化;它查看程序并仅存储对已定义的相同字符串的一个引用。因此,您的指针将在应用程序的整个生命周期内保持有效。

你不应该依赖这个。您不能保证所有编译器都会进行此优化。创建变量时保留该变量,不再需要时释放它。

It sounds like you aren't retaining the string and because of this when you try to access it later on it has been deallocated. If you aren't familiar with memory management, take a look at the Memory Management Programming Guide from Apple.

The reason -stringWithString: doesn't break is likely because the compiler is doing some optimisation with string literals; It looks through the program and stores just one reference to identical strings that are defined. Because of this your pointer will remain valid throughout the lifetime of the app.

You should not rely on this. You cannot guarantee that all compilers will do this optimisation. Retain the variable when you make it and release it when you stop needing it.

白昼 2024-10-25 21:51:29

编译器很聪明,它不会创建数十个不同的 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 对象将被释放,并且您将得到错误的访问异常。

您违反了内存管理规则,但如果您只使用字符串文字,您将永远不会注意到它。直到编译器的行为发生变化。

因此,要正确行事,学习正确的内存管理,不要依赖内部机制。如果稍后需要,请保留所有自动释放的对象。即使它们指向字符串文字

the compiler is smart, and instead of creating dozens of different NSString instances that all hold the same value he creates one instance that can't be released and all the other instances just point to the NSString that is hardcoded in your program.

And because the hardcoded NSString gets never deallocated you can use it even after the autorelease pool would have deallocated it.

This just covers your wrong memory management. And you should definitely not rely on this behaviour.


Edit. there is not much more to say. The NSString that you've created with stringWithString:literal will simply point to the location of literal in memory.

A little example:

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);

you will see they all point to the same address.

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

And all of them will never get deallocated. So you could access string5 from some other method in your code and it would still point to the address 295740, and the NSString "Foo" would still be there.

But a NSString object that does not point to a string literal would be deallocated at this time, and you would get a bad access exception.

You are violating the memory management rules but you will never notice it if you only use string literals. Until the behaviour of the compiler changes.

So do it right, learn proper memory management and don't rely on internals. Retain all your autoreleased objects if you need them later. Even if they point to string literals

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文