1

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 !

EmptyStack
  • 51,274
  • 23
  • 147
  • 178
Pierre
  • 10,593
  • 5
  • 50
  • 80
  • 1
    possible duplicate of [Does @"some text" give an autoreleased or retain 1 object back?](http://stackoverflow.com/questions/6069459/does-some-text-give-an-autoreleased-or-retain-1-object-back) –  Sep 12 '11 at 11:13
  • don't think so. When you're using init key word you own directly the object. If you want to have an autorelease you must write : stringWithString: – Pierre Sep 12 '11 at 11:15
  • Conceptually, you’re right. Internally, it’s not what happens as I explained in the comments of the accepted answer to that question. –  Sep 12 '11 at 11:17
  • Oh sorry I didn't see it was a link :) Thanks ! – Pierre Sep 12 '11 at 11:19
  • Come to think of it, your question is _related_ to that other question, not exactly a duplicate. Sorry for the close vote. –  Sep 12 '11 at 11:21

2 Answers2

3

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
Community
  • 1
  • 1
2

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

MByD
  • 135,866
  • 28
  • 264
  • 277