Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing a released NSString doesn't make the app crash

I know this is probably the exact opposite of the questions asked on Stackoverflow, but something really weird happened to me today. I was trying to show someone how to work with Instruments and NSZombies, so I tried to create a crash.

I declared a NSString, released it and then tried to access it but the app didn't crash

NSString* test = [[NSString alloc] init];
[test release];
NSlog(@"%@", test);

I even tried to release it twice, but it still didn't make the app crash, it just printed null.

Can anyone please explain me what I did wrong or where is the flaw in my logic?

Thank you


EDIT : I tried something like this too and still no crash

NSString* test = [[NSString alloc] init];
test = @"something";
NSlog(@"%@", test);
[test release];
NSlog(@"%@", test);

I even added two consecutive releases, and a test = nil; after a release, just to make sure.

like image 814
BBog Avatar asked Nov 21 '25 10:11

BBog


2 Answers

NSString may sometimes behave strangely.

In your example, you allocated a NSString without data.
That's the reason why it doesn't crash.

Allocating a NSString without data has no sense, as NSString objects are immutable.
In such a case, NSString will return a kind of singleton instance, meaning you can't release it (well, you can, but it will have no effect).
Every time you allocate a NSString object this way, the same instance will be returned.

Try this instead:

NSString * test = [ [ NSString alloc ] initWithCString: "hello, world" encoding: NSUTF8StringEncoding ];

[ test release ];

NSLog( @"%@", test );

Then it will crash, as expected...

To prove what I have explained earlier, try this:

NSString * test1 = [ [ NSString alloc ] init ];
NSString * test2 = [ [ NSString alloc ] init ];

NSLog( @"OK: %p %p", test1, test2 );

You can see the same address is printed, meaning only one object is allocated (the "singleton" one, for NSString objects without data).

EDIT

I've seen on your comment that you tried to "give the string a value".
This is not possible using NSString, as they are immutable.

I guess you tried this:

NSString * s = [ [ NSString alloc ] init ];

s = @"hello, world";

In such a case, you are not giving a value!

You are re-assigning a pointer!

It means your s variable (which is a pointer) will then point to another string object.
And it also mean you won't be able to access your previously allocated string, as you just lost the pointer to it.

If you want string objects that can be changed, take a look at the NSMutableString class.
But keep in mind that changing a pointer value is not the same as changing an object's value!

like image 89
Macmade Avatar answered Nov 24 '25 01:11

Macmade


There are two things going on in your example.

First, nothing else happened between your release and your NSLog that would modify the memory where your string was stored, so it happens to still be intact. You can't rely on that.

Second, the system has a special case for [[NSString alloc] init]. It returns a predefined object of type __NSCFConstantString that is never deallocated. If you print its reference count, you'll see that it is 2147483647 (0x7fffffff). That is a magic number indicating that any attempt to retain or release the object is ignored.

like image 44
rob mayoff Avatar answered Nov 24 '25 01:11

rob mayoff