views:

141

answers:

6

I am having trouble understanding why NSLog reports "dog" when the code is run. I understand about retain counts and dealloc e.t.c. What simple thing am i missing ?

NSString *newFoo = @"dog";
 [newFoo release];
 NSLog(newFoo);
A: 

You are de-allocating the chunk of memory the pointer's pointing at, but the data is still there.

Releasing it doesn't automatically zeroes out that part of the memory.

So you can still read the data out just fine but it's just might be snapped (allocated) by something else down the line... but just not yet.

I'm not an ObjC coder by trade but as since its compatible with C that's I'm guessing from my C experience.

chakrit
The pointer is not deallocated
Mark
Only by a special case for string literals. Change that to any other class and any other initialization scheme and chakrit is 100% correct.
Randolpho
One flaw and you get a flurry of downvotes. Guess that's what "community" means.
chakrit
+4  A: 

I believe it's because @"dog" is effectively treated as a constant by the compiler. It creates some subclass of NSString (which is a class cluster) which persists for the lifetime of the application.

Just discovered this question for the definitive answer, which is essentially the same as mine.

Gregory Higley
A: 

Even though newFoo has been released, meaning that its memory has been marked as re-allocatable by the runtime, the memory itself is not overwritten. Because newFoo still points to the location in memory where your string existed, the memory is still there and is still used.

The only reason you're not getting a segfault is that you just happen to not have allocated new memory over the location where newFoo pointed.

Bottom line: you're getting lucky. Never reuse a pointer that you've released.

Randolpho
-1 for being wrong: Luck doesn't enter into it; you simply cannot release string literals.
Williham Totland
Maybe I'm wrong in the case of string literals, but I'm right in every other case, and my bottom line is 100% correct. Never reuse a pointer that you've released. Granted, releasing a literal is a special case that works, but the general case is still valid.
Randolpho
Randolpho is right in principle. That the string literal is a special case is an implementation detail.
Chuck
+7  A: 
[@"String Literal" release];

is a noop;

NSString *literal = @"String Literal";
[literal release];

is also a noop. This is only the case for string literals; and you should never expect this behaviour anywhere else. (This is to say; even though you tell the object to release, it just doesn't.)

Williham Totland
Exactly, although you may have stated it more clearly than I did.
Gregory Higley
And you should certainly never consider this behavior when programming. The retain count is an implementation detail, the only thing you should care about is balancing your retains with your releases.
bbum
A: 

Although the object is probably released (not sure how Obj-C handles strings internally, some languages basically cache strings), you have not writted anything new in the memory of newFoo after you released it. The memory where the string was stored keeps its content, but could be overwritten at any time.

newFoo still points to the same adress in memory, but that memory could become anything else at any moment.

The way to really be sure that you don't point to potentially dirt memory is to set newFoo to nil after you released it.

mrueg
+2  A: 

A String Literal is a special case.. http://thaesofereode.info/clocFAQ/

But in general assuming you are not using garbage collection just stick to the few simple rules..

http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

more pertinently.. retain an object when you need it to stick around - balance it with a release when done. If you didn't create or retain it, you don't need to release it.

Sending -release to an object isn't like freeing the memory, it only signals that you are done with it. It may well still be around or it may not. You have no way of knowing, you don't need to know, and you shouldn't try to find out if it is used elsewhere, if clever apple code has decided to cache it, if it's a singleton, etc.

It may well still be valid but when you have sent release you have effectively said "I'm done" and not "reclaim this memory".