分配与释放问题

发布于 2024-12-04 04:00:11 字数 268 浏览 0 评论 0原文

我试图向朋友解释 iOS 上的内存管理,但我向他展示了错误的代码。但是当我启动该应用程序时,它正在运行,但我不知道为什么。 这是片段:

NSString *myString = [[NSString alloc] initWithString:@"myString"];
[myString release];
NSLog(@"%@",myString);

我不明白为什么我的 NSLog 正在工作...... 你有一些解释吗?

谢谢 !

I'm trying to explain memory management on iOS to a friend and I'm showing him a wrong code. But when I'm launching the app, it's working and I don't know why.
Here's the snippet :

NSString *myString = [[NSString alloc] initWithString:@"myString"];
[myString release];
NSLog(@"%@",myString);

I don't understand why my NSLog is working ...
Do you have some explanations ?

Thanks !

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

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

发布评论

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

评论(2

总以为 2024-12-11 04:00:11

关于您的示例,有两件事需要记住。

  1. 正如 MByD 所解释的,访问已被释放的对象是未定义的行为。它可能会也可能不会使你的程序崩溃——这取决于分配给该对象的内存是否已被重用以及那里放了什么。在某些情况下,内存尚未被重用(您可能认为该对象仍然存在,但该对象实际上是一个幽灵对象),在其他情况下,内存可能已被另一个对象重用Objective-C 对象(程序不会崩溃,但您会看到不同的对象),在其他情况下,内存可能已被非 Objective-C 对象的对象重用(在这种情况下,程序可能会 - 但不会必然 — 崩溃)。

  2. 您的字符串对象是一个常量字符串。正如这个问题的答案 及其注释,常量字符串永远不会被释放。当您发送 -[NSString initWithString:] 并传递常量字符串作为参数时,Cocoa 返回原始常量字符串,因此您的代码实际上与 NSString *myString = @"myString"; 相同。。但这是 Cocoa 内部的实现细节。生产代码应始终考虑由 +alloc (以及通常后续的 -init)返回的对象归调用者所有,当调用者不感兴趣时​​应将其释放它们不再可用,并且在释放后将不可用。

为了进行实验,请尝试以下代码:

#import <Foundation/Foundation.h>
#include <stdio.h>

int main(void) {
    [NSAutoreleasePool new];

    NSString *s1 = [[NSString alloc] initWithString:@"myString"];
    NSString *s2 = [[NSString alloc] initWithString:@"myString"];
    NSString *s3 = [[NSString alloc] initWithString:@"myString"];
    NSString *s4 = [[NSString alloc] initWithString:@"myString"];

    printf("s1 = %p\n", s1);
    printf("s2 = %p\n", s2);
    printf("s3 = %p\n", s3);
    printf("s4 = %p\n", s4);

    [s1 release];
    [s2 release];
    [s3 release];
    [s4 release];

    return 0;
}

从概念上讲,s1s2s3s4 应该是不同的对象。但是,通过运行此程序,您可以看到它们实际上是同一个对象(它们具有相同的地址):

$ ./a.out
s1 = 0x10080b090
s2 = 0x10080b090
s3 = 0x10080b090
s4 = 0x10080b090

There are two things to bear in mind with regard to your example.

  1. As MByD explained, accessing an object that’s been deallocated is undefined behaviour. It might or might not crash your program — it depends on whether the memory that had been allocated to that object has been reused and what’s been put there. In some cases the memory hasn’t been reused yet (and you might think the object is still alive but that object is in fact a ghost object), in other cases the memory may have been reused by another Objective-C object (the program won’t crash but you’ll see a different object) and in other cases the memory may have been reused by something that’s not an Objective-C object (in which case the program will likely — but not necessarily — crash).

  2. Your string object is a constant string. As explained in the answer to this question and its comments, a constant string is never deallocated. When you send -[NSString initWithString:] passing a constant string as the argument, Cocoa returns the original constant string so your code is effectively the same as NSString *myString = @"myString";. This is an internal Cocoa implementation detail though. Production code should always consider that objects returned by +alloc (and, usually, subsequent -init) are owned by the caller, should be released when the caller is not interested in them anymore, and won’t be available after deallocation.

For the sake of experimentation, try the following code:

#import <Foundation/Foundation.h>
#include <stdio.h>

int main(void) {
    [NSAutoreleasePool new];

    NSString *s1 = [[NSString alloc] initWithString:@"myString"];
    NSString *s2 = [[NSString alloc] initWithString:@"myString"];
    NSString *s3 = [[NSString alloc] initWithString:@"myString"];
    NSString *s4 = [[NSString alloc] initWithString:@"myString"];

    printf("s1 = %p\n", s1);
    printf("s2 = %p\n", s2);
    printf("s3 = %p\n", s3);
    printf("s4 = %p\n", s4);

    [s1 release];
    [s2 release];
    [s3 release];
    [s4 release];

    return 0;
}

Conceptually, s1, s2, s3, s4 should be different objects. However, by running this program you can see that they are effectively the same object (they have the same address):

$ ./a.out
s1 = 0x10080b090
s2 = 0x10080b090
s3 = 0x10080b090
s4 = 0x10080b090
不爱素颜 2024-12-11 04:00:11

这是一种未定义的行为。您无权访问该字符串,但它可能可用。

This is an undefined behavior. You are not allowed to access this string, yet it might be available.

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