分配和释放问题

时间:2011-09-12 11:07:53

标签: objective-c nsstring

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

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

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

谢谢!

2 个答案:

答案 0 :(得分:3)

关于你的例子,有两点需要注意。

  1. 正如MByD所解释的那样,访问已被解除分配的对象是未定义的行为。它可能会或可能不会使程序崩溃 - 这取决于分配给该对象的内存是否已被重用以及放在那里的内存。在某些情况下,内存尚未被重用(并且您可能认为该对象仍处于活动状态但该对象实际上是 ghost对象),在其他情况下,内存可能已被另一个重用Objective-C对象(程序不会崩溃,但你会看到一个不同的对象),而在其他情况下,内存可能已经被不是Objective-C对象的东西重用(在这种情况下程序很可能 - 但不是必然 - 崩溃)。

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

  3. 为了实验,请尝试以下代码:

    #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
    

答案 1 :(得分:2)

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