Objective-C release is not called explicitly - iphone

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString * str = [[NSString alloc] initWithString:#"test"];
[str release];
int i = 999999999;
while(i-- > 0) {}
NSLog(#"%#", str);
[pool drain];
Output: test
Why didn't release work?
How can I immediately delete the object from memory?
Xcode Version 4.0 iPhone Application
~SOLVED~
Thank's to all for answers.
I've got a lot of useful information about this question. I'm going to use NSString *str = #"text" instead of NSString *str = [[NSString alloc] initWithString:#"text"];
i've understood that release just "marks" memory as "willing to be freed", but not freeing it immediatly

It did work. You have relinquished ownership of that object, and when the system determines that it is no longer owned, it will be marked available for reuse by the system. That may happen immediately, if you were the only owner of the string. It may happen at some later point, if creation of the string caused it to be autoreleased internally. Or, as Dave DeLong points out, the system may optimize it into an object that is never released.
In your case, it's being optimized into a constant string, which will exist for the life of the program. If you were to use an NSMutableString instead of an NSString, you'd see funky behavior that would probably not crash, but wouldn't print what you expected. (See this question for an example.)
If you used an NSArray instead, it would be deallocated when you called release, but you'd still see your NSLog example work correctly until you allocated some other object. Deallocation just marks the memory as available for reuse; it doesn't actually clear it out. So if you passed the array to NSLog, that memory hasn't been changed and thus it still prints correctly.
The key point in all of this, though, is to recognize that calling release will not necessarily cause the object to be deallocated. It may continue to exist for any number of reasons. But once you call release, you have relinquished ownership of the object. If you continue using it after that point, the system is free to do all sorts of weird things at its own will, as demonstrated.

Release does work but what you are attempting to do has undefined behavior, and when using a NSString and a literal you may also get different behavior. What is happening is although your object is released the memory at that location is reclaimable and has not changed and when it goes to print it it is still valid. Since it is a NSString a message to description is not necessarily sent and that is why you are not getting an exception for attempting to message a deallocated object.
This question has some good information about NSString and NSLog.

When you do:
NSString * str = [[NSString alloc] initWithString:#"test"];
This gets optimized into:
NSString * str = #"test";
You can't release a constant string, because it's hardcoded into the application binary.
Proof:
NSString *s = [NSString alloc];
NSLog(#"%p", s);
s = [s initWithString:#"foo"];
NSLog(#"%p", s);
s = #"foo";
NSLog(#"%p", s);
Logs:
2011-04-12 10:17:45.591 EmptyFoundation[6679:a0f] 0x100116370
2011-04-12 10:17:45.599 EmptyFoundation[6679:a0f] 0x100009270
2011-04-12 10:17:45.604 EmptyFoundation[6679:a0f] 0x100009270
You can see that the result of +alloc is different from the result of -initWithString:, and the result of -initWithString: is equivalent to the constant string. Basically, -initWithString: says "aha, i'm going to be an immutable string, and I'm being given an immutable string! I can just take a shortcut, destroy myself, and return the parameter, and everything will still work the same"

You're using a bad pointer in you NSLog(). You happen to be getting lucky in this case, but you should expect code like this to crash or fail in other ways.

There is no need to delete the memory block, this will use up an unneeded cycle.
The memory will be overridden when an new object is allocated an occupy that memory block.

Related

Why UPDATE statement works with initWithFormat and NOT with stringWithFormat?

I was having an issue with my UPDATE statement as I was telling here: Update issue with sqliteManager
I found out that initWithFormat WORKS
NSString *sqlStr = [[NSString alloc] initWithFormat:#"UPDATE User SET Name = :Name WHERE Id = :Id"];
BUT not stringWithFormat:
NSString* sqlStr = [NSString stringWithFormat:#"UPDATE User SET Name = :Name WHERE Id = :Id"];
Why is this as such? I would like to understand the logic/reasoning behind..
I am guessing that it has to do with the memory management of the string, it might not have been sufficiently retained so it is getting cleaned up before for it is getting used. The difference between the two methods are defined here
I have just found something interesting from this thread: How to refresh TableView Cell data during an NSTimer loop
This, I believe, is the reasoning behind..
I quote what "petergb" said:
[NSString stringWithFormat:...] returns an autoreleased object. Autoreleased objects get released after control returns from the program's code to the apple-supplied run-loop code. They are more or less a convenience so we don't have to release all the little objects that we use once or twice here and there. (For example, imagine how tedious it would be if you had to release every string you created with the #"" syntax...)
We can tell stringWithFormat: returns an autoreleased object because, by convention, methods who's names don't start with alloc or copy always return auto-released objects. Methods like this are said to "vend" an object. We can use these objects in the immediate future, but we don't "own" it (i.e. we can't count on it being there after we return control to the system.) If we want to take ownership of a vended object, we have to call [object retain] on it, and then it will be there until we explicitly call [object release] or [object autorelease], and if we don't call release or autorelease on it before we lose our reference to it by changing the variable to something else, we will leak it.
Contrast with [[NSString alloc] initWithFormat:. This method "creates" an object. We own it. Again, it will be there until we explicitly call [object release].

Autoreleasing twice an object

NSString *str = [[[[NSString alloc]init]autorelease]autorelease];
str = #"hii";
NSLog(#"%#",str);
Can any one help me to tell about this code. Autoreleasing the object twice what will happened. When i run the code i didn't get any zombie. why it so.
The object gets released twice when the autorelease pool is destroyed, which is probably going to be at the end of the run loop iteration. Why it doesn't crash is, that NSString returns singletons for some instances, for example the empty string you create or string literals (you should NOT depend on it, thats just what currently happens!), these objects won't be deallocated and this is why you don't get a zombie.
First of there is no reason to call autorelease twice.
Once an object is marked as autorelease, calling autorelease on it again will just be ignored. See https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/nsautoreleasepool_Class/Reference/Reference.html
But in the exmaple you posted you are creating an empty string:
NSString *str = [[[[NSString alloc]init]autorelease]autorelease];
Then you assign an other string to it:
str = #"hii";
This means that the first string you allocated is just going to be leak, you did autorelease it so it will be cleaned up at the end. But there is not reason to allocated the string in fist place.
You could just do:
NSString *str =#"hii";
NSLog(#"%#",str);

Difference between these two NSString methods

So I just got asked this at an interview today and after some googling am still unable to figure out the answer (in fact I couldn't even find any code at all which used the [NSString string] method).
What is the difference between
NSString *someString = [NSString string];
NSString *someString = [[NSString alloc] init];
Now my initial thoughts were that [NSString string] would return an object which would be autoreleased whereas using alloc and init would return an object which has been retained. However it seems that this answer was incorrect.
I've looked at the NSString class reference in the apple docs but all it says is
Returns an empty string.
+ (id)string
Return Value
An empty string.
Could somebody explain to me exactly what the difference between these two are?
Was that your response, and did you ask why your answer was incorrect? I ask because your assumption is mostly correct (at a higher level).
It's not exactly 'retained' when returned from alloc+init, it is an object you hold one reference to, and should balance with a release or autorelease. For the convenience constructor (+[NSString string]), you are returned an object which you hold zero references to, but one which you can expect to live until the current autorelease pool is popped unless you send it an explicit retain (assuming MRC or ARC, since it is tagged iOS).
At the lower level, you could make some guesses, but I wouldn't expect that question in many objc interviews (unless you told them you were mid or senior level). Basically, it is implementation defined, but both forms could return the same static, constant NSString (that may have been what the interviewer was looking for). To illustrate:
#implementation NSString
static NSString * const EmptyNSString = #"";
- (id)init
{
self = [super init];
[self release];
return EmptyNSString;
}
+ (id)string
{
return EmptyNSString;
}
...
Again, that's implementation defined, but an obvious optimization. As well, that optimization makes physically subclassing concrete immutable types (NSString) difficult for mutable variants (NSMutableString) in some cases.
Now my initial thoughts were that [NSString string] would return an object which would be autoreleased
Technically, it’s a placeholder string that is constant, i.e., it lives throughout the entire program execution, never being released. It’s not an autoreleased string. Conceptually, and this is what I’d focus as an interviewer, it’s a string (an empty string) that is not owned by the caller, hence the caller shouldn’t release it.
whereas using alloc and init would return an object which has been retained
Technically, it’s a placeholder string that is constant, i.e., it lives throughout the entire program execution. In fact, it’s the same object as the one above, and it is not retained. Conceptually, and this is what I’d focus as an interviewer, it’s a string (an empty string) that is owned by the caller, hence the caller is responsible for releasing it when it’s not needed any longer.
The correct answer is that
NSString *someString = [NSString string];
gives you an empty string that you do not own and that you must not release (according to the memory management rules)
whereas
NSString *someString = [[NSString alloc] init];
gives you an empty string you do own and that you must release (according to the memory management rules).
Without poking into the implementation, you can't say anything else about those two strings. You can't say that they are autoreleased, because they might not be and you can't say what the retain count will be.
In actual fact, you'll probably get (in both cases) the same pointer to a constant object of some NSString subclass, probably with a retain count of UINT_MAX which is used by the run time as a flag to disable normal retain release behaviour for constant strings. I haven't actually tried the above because nobody except the maintainers of the Objective-C SDK needs to care.
You don't often see
NSString *someString = [NSString string];
because it's the same as
NSString *someString = #"";
which is shorter. It's usually used to create an empty NSMutableString
NSMutableString* s = [NSMutableString string];
The only thing I can imagine is that:
Won't allocate memory since it is not made with alloc. It is a constant (an empty string) made by the system and doesn't need to be released.
You allocate the memory for the NSString yourself which means you have to keep track if the NSString still 'lives' or not when you are done with it, and thus need to release it.

ObjctiveC yet another retain-copy-release error [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Objective C alloc/release error
When I try the code below it crashes with BAD_ACCESS if I release newString. What am I missing here?
As far as I know, when I use "copy" as an accessor I got the ownership of the object, so even should I release the other referencing pointer, retain count should still stay 1+, so that object should still be in memory?
P.S. This is a singleton class if it makes a difference.
.h file
NSString *originalString;
#property (nonatomic,copy) NSString *originalString;
.m file
#synthesize originalString;
...
NSString *newString = [[NSString alloc] init...];
self.originalString = newString;
[newString release]; //this lines makes it crash
I've also tried
self.originalString = [newString copy];
with no luck..
Have you tried using retain instead of copy?
http://wiki.cs.unh.edu/wiki/index.php/Objective_C_Property_Attributes#Setter_Semantics
I'm not really sure whether or not this would actually work if copying doesn't, but using retain instead of copy should cause the reference count to the string to increment by 1 when assigned to the property, bringing it up to 2 from the 1 it was when the string was alloced, so when you use [newString release]; on the line after the property assignment, the string should end up with reference count 1 and thus continue to exist.
[newString relase]; //this lines makes it crash
relase probably isn't the name of a method. Did you mean release?
Assuming the above was just a typographical error in your question, and not an error in your code, then your code is correct, and you'll need to provide more information about the error. Pasting the actual code of the method in question would be helpful in that case.
this code looks correct, are you sure the crash isn't somewhere else?
EDIT: as noted in the comments, NSString being immutable won't cause the copy to allocate a new object. I've edited the answer for the mutable case, just in case someone stumbles into this later and doesn't read the whole thing.
Now back with our regular programming.
Don't know if this might be the problem, but note that, if you were using a mutable object like NSMutableString, with copy you would not increment the retain count, you would effectively create a new object, so what would happen:
NSMutableString* newString = [[NSMutableString alloc] init..]; // allocate a new mutable string
self.originalString=newString; // this will create yet another string object
// so at this point you have 2 string objects.
[newString relase]; //this will in fact dealloc the first object
// so now you have a new object stored in originalString, but the object pointed
// to by newString is no longer in memory.
// if you try to use newString here instead of self.originalString,
// it can indeed crash.
// after you release something, it's a good idea to set it to nil to
// avoid that kind of thing
newString = nil;
Have you tried just adding autorelease to your *newString init? Then just take out the manual release all together.
NSString *newString = [[NSString alloc] init...] autorelease];
You may consider to migrate your codes to Xcode 4.1 with ARC, then you would not need to worry about retain and release of objects.

Memory leak for variables created inside methods

To me, the following code looks like it will create a leak -- I might be wrong about this though:
-(NSString*) myString{
NSString* foo = #"bar";
return foo;
}
My question is:
1) Will is create a memory leak as foo is not released?
2) If it IS a memory leak then how do I avoid it?
It is not a leak. #"bar" is a statically allocated string and thus foo doesn't need to be retained. You can handle these strings like autoreleased objects although they will resist in memory for the runtime of the application.
You can turn it into a leak by returning [foo retain] or [foo copy].
Technically it makes no sense to retain static variables. But if you copy them, you have to release them.
Short answer. This code will not give a leak.
Long answer:
With NSString it is not always visible leak, because of strings intern and because you do not call alloc/new/copy methods. But yes, this is a classic point of memory leak in general.
There are two ways of dealing with it.
tracing all objects that you are returning from this (or similar) method and releasing them. That's extremely buggy possibility and a very bad one almost every time.
returning autoreleased instance. In fact, you did something like it implicitly here. This string assignment is similar to:
NSString *foo = [NSString stringWithString:#"bar"];
And this one is similar to:
NSString *foo = [[[NSString alloc] initWithString:#"bar"] autorelease];
So, you will return an object, that has retain count 1, but is autoreleased. So, when NSAutoreleasePool will be drained, this object will go away.