开发者

Allocation and release problem

开发者 https://www.devze.com 2023-04-04 11:15 出处:网络
I开发者_StackOverflow\'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.

I开发者_StackOverflow'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 !


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


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

0

精彩评论

暂无评论...
验证码 换一张
取 消