Objective-C on iPhone release problem - iphone

I have a problem that I am getting EX_BAD_ACCESS when calling release on an NSStream object in my dealloc on the iPhone.
The following code
- (void)dealloc {
DLog(#"dealloc started for: %#",self);
#synchronized(self) {
lookupCount--;
if (lookupCount==0) {
UIApplication* app = [UIApplication sharedApplication];
app.networkActivityIndicatorVisible = NO;
}
}
DLog(#"inStream retain count before release: %d",[inStream retainCount]);
[inStream release];
DLog(#"outStream retain count before release: %d",[outStream retainCount]);
[outStream release];
[queryToSend release];
[resultString release];
[data release];
[super dealloc];
NSLog(#"dealloc finsihed for : %#",self);
}
crashes with EX_BAD_ACCESS on the
[outstream release];
line.
Log output is as follows
2009-04-29 13:16:28.547 App[30580:20b] -[SimpleQuery dealloc] [Line 160] dealloc started for: <SimpleQuery: 0x56e540>
2009-04-29 13:16:28.547 App[30580:20b] -[SimpleQuery dealloc] [Line 168] inStream retain count before release: 1
2009-04-29 13:16:28.548 App[30580:20b] -[SimpleQuery dealloc] [Line 170] outStream retain count before release: 1
Wondering if anyone has any ideas why this might be ?

In a comment you said this about outstream
It's created by a call to
getStreamsToHostNamed:port:inputStream:outputStream:
which shouldn't return autoreleased
objects I don't think.
It is in fact, auto-released. Unless you are retaining that object somewhere in your code, you are not responsible for the memory management of it.
You should take a look at the Apple Memory Management Guidelines.
Many classes provide methods of the
form +className... that you can use to
obtain a new instance of the class.
Often referred to as “convenience
constructors”, these methods create a
new instance of the class, initialize
it, and return it for you to use.
Although you might think you are
responsible for releasing objects
created in this manner, that is not
the case according to the policy Cocoa
set—the method name does not contain
"alloc" or "copy", or begin with
"new". Because the class creates the
new object, it is responsible for
disposing of the new object.

Some potential problems:
You're locking on self to do the lookupCount decrement loop, which I assume means you expect this code to be run from different threads. That should be a red flag right there, since if you're deallocating an instance from two threads simultaneously, one of those threads is going to end up trying to dealloc an already deallocated instance.
The final NSLog call will try to print self which would already have been deallocated.
I know none of these pertains specifically to [outStream release], but they could be related. You might want to try debugging this with NSZombieEnabled to get more info.
Also, make sure releasing inStream doesn't also implicitly release outStream, etc.

Related

iPhone Memory Management

Hello Stackoverflow fellow family members!
I've got question regarding memory management in iPhone.
What I did understand was below method
-(void) dealloc
{
// something else to release whatever
// such as Object Created using keyword 'alloc'
// but also Object destroy here its retain value reaches iff 0
// if I do put here NSLog(#"%d", [obj retainCount]); and when it reaches
// not equal to 0 means failure with memory leak.
[super dealloc];
}
So am I understand right? or It is still alight even if retain count reachs > 0 here?
The reason I ask about this question because,
I checked with
NSLog(#"%d", obj.retainCount);
to check the retain count of the object and received value 3. So I tried to release here 3 times to make retainCount here equal to 0, but compiler gives me critical error.
Please, I'm new to the memory de-allocation and retain, release.
Object that I used was 'UIImageView' object and created another instance as,
UIImageView *imageView = //da da~ with UIImage
UIImageView *instance;
// at this point retain count was '1'
instance = imageView;
//[imageView retain];
// at this point retain count was '2'
[self.view addSubView: imageView];
// at this point retain count was '3'
[imageView release];// crashes
// at this point retain count was '2'
but if I do
// but if I add retain on the 'instance = imageView'
// such as
instance = imageView; // then
[imageView retain];
// works but still count is 2...
Thank You.
retainCount is not a reliable debugging-tool:
other objects might still hold references to obj
there are objects that you can't destroy (e.g. string constants)
objects are deallocated if released with a retain count of 1
What you should take care of instead:
balancing references you have with the right amount of release/autorelease
using the Analyzer
using Leaks
The normal process for overriding dealloc is to release any objects that have been previously retained (or alloc'ed) by this instance.
So if somewhere else in the object you have called an alloc or retain method your dealloc would look like:
-(void)someOtherMethod
{
UIImageView *imageView = //da da~ with UIImage
UIImageView *instance;
instance = imageView;
[instance retain];
}
-(void) dealloc
{
//release any retained objects here
[instance release]
[super dealloc];
}
Note that it doesn't matter if the release count hasn't dropped to zero after your particular release, that just means that some other bit of code has also retained the object memory (and that other bit of code will be responsible for releasing it).
Hope this helps.
That's not correct and you should rarely use retainCount. It does not have to be 0 at this point as other objects could have references to the objects you are releasing. What is important to do in dealloc is to release objects that you have ownership on. Which would be objects created with alloc or new etc.

objective-c over-releasing in dealloc

Is mystring over-released?
-(void)dealloc {
[mystring release];
[mystring release];
[super dealloc];
}
I assume this will not based on [nil release] does nothing:
-(void)dealloc {
[mystring release];
mystring = nil;
[mystring release];
[super dealloc];
}
-EDIT-
Let's say I allocate mystring in init and release it in doSomething:
-(id)init {
if (self = [super init]) {
mystring = [[NSString string] retain];
}
return self;
}
-(void)doSomething {
[mystring release]; // for some good reason
// ...etc
}
Now to avoid over-releasing in dealloc based on my example above do I have to explicitly do this in the doSomething method?
-(void)doSomething {
[mystring release];
mystring = nil; // <- is this mandatory to avoid over-releasing in dealloc?
}
The big question is do I have to explicitly set it to nil when I release it somewhere else in the class to avoid over-releasing in dealloc?
So could I do as many releases as I want in dealloc based if I explicitly set to nil in doSomething?
-(void)dealloc {
[mystring release];
[mystring release]; // <- does nothing because mystring explicitly nil?
}
For your first example, the answer is probably!
In general, each object that holds a reference to another object should retain it until they're done, then call release once, however in some highly exotic (and generally poorly written) cases this may not hold. If you retain the object x times, you need to release it x times, and other cases of poor memory management. But best practice, yes, one retain, one release, don't release more than you retain!
There are two risks with over-releasing like this:
The first is if the first release call makes the refcount of mystring equal to 0, it will be dealloc'd, and then you're sending a message to a piece of memory that is no longer a valid object. Objective-C doesn't really like this, and may react in a variety of ways, including CRASHING. Sending messages to nil, kosher, messages to things dealloc'd, not so much.
The second is if the refcount isn't zero, you just released someone else's reference, so at some point in the future, an object that has a reference to mystring may think that reference is valid and it won't be because it was dealloc'd when the refcount hit zero on a subsequent release call. This will be harder to detect than the previous error, where a debugger will at least show you the real area the problem originates from in the stack frame trace.
Your second example is correct - sending a message to nil does nothing. If you fear you'll do things like this, be sure to set your variables to nil after releasing.
EDIT: Yes. That's what you should do if you intend to release in more than one place like that, however depending on the application, you might consider using an auto-release pool.
It all depends on how many time you retained mystring. If you have two members that may refer to the same object and both retain the object, they should both release the object.
So your first example would be correct if you use mystring = [[somestring retain] retain];
The second one will be better. Because when you release, you release the memory the mystring point to not the memory of the mystring. So, the mystring is not null and if somebody accidentally use it, your app will crash. It also depends on how many times your mystring is retained

What is the best way to dealloc memory in Objective C?

I have a query regarding the memory management.
Let's begin with an example. Assume we have a class as follows.
#interface myClass : NSObject {
NSString *xyz;
}
#end
Now, see the implementation.
#interface myClass : NSObject {
NSString *xyz;
}
#end
#implementation myClass
-(void)abc{
// xyz allocted here
}
-(void)pqr{
// retained or copied many times or may not a single time
}
-(void)mno{
// retained or copied many times or may not a single time
}
-(void)jpg{
// may be released more than one time or may be not
}
//-(void)dealloc{
// [xyz release];
// [super dealloc];
//}
//
//-(void)dealloc{
// if(xyz!=nil && [xyz retainCount]>0){ [xyz release]; xyz=nil; }
// [super dealloc];
//}
-(void)dealloc{
if(xyz!=nil){
while([xyz retainCount]>0)
[xyz release];
xyz=nil;
}
[super dealloc];
}
#end
In above code. I have three dealloc functions. Which one is preferable? If none of these, then please suggest yours.
I am confused because Objective C says, object must be released each time = each time alloc/retained.
But most of the sample code has just single statement "[xyz release];" doesn't it create a memory leak?
This is absolutely wrong:
while([xyz retainCount]>0)
[xyz release];
xyz=nil;
retainCount will never return 0, because as soon as you are at a retainCount of 1 and the object is released, the runtime just deallocates it right then and there, never decrementing the retainCount. Even if it did decrement the retainCount, the object is now deallocated. How are you going to ask it what it's retainCount is?
In a nutshell, your design is wrong. If you can't keep track of how often you've retained an object in a smarter way, then you will have memory leaks and most likely crashes from overreleasing objects (this while loop will crash your app).
If you absolutely can't change your code (I wouldn't believe you if you said you couldn't), then you'd want to keep a second integer ivar indicating how many times you've retained xyz, and then use that to figure out how many times you should release it. (However, this should be an absolute last ditch effort, as in Armaggeddon will happen if you don't get this working in 30 seconds. You should really refactor your code first.)
In addition, you've forgotten the call to [super dealloc] in your dealloc method.
- (void)dealloc {
[xyz release];
[super dealloc];
}
...is the correct version. In Objective-C, you generally shouldn't use the retainCount method.
If you want to be very safe, you can also write:
- (void)dealloc {
[xyz release], xyz = nil;
[super dealloc];
}
The idea is that myClass has a member variable (in your case, xyz). When a myClass object gets created, it should create (or get a reference to) xyz by adding only 1 to the retain count (whether through retain or other means depends on the situation).
It would not be a good idea in each method to retain xyz with releasing it again. So at the end of each method, the the local object should have no more holds on xyz than it had at the beginning of the method.
By the time dealloc gets called, only that single retain hold should remain on xyz (as far as the myClass object is concerned), so a single call to release will suffice. It is not a good idea to release until the retainCount is zero because another object somewhere might be using it.
To directly answer your question, use this dealloc:
-(void)dealloc{
[xyz release];
}
objects those are retained during the poperty declaration need to be released in the dealloc method. So if you are declaring
#property(nonatomic, retain)NSString xyz;,
you need it to be released in dealloc as
-(void)dealloc{
[xyz release];
[super dealloc]
}
Any other allocated memory should be released immediately after the last use of that object from within your methods.
So if you are allocating xyz, in
-(void)abc{
// xyz allocted here
}
then you shoud release it at the end of the same method.
-(void)abc{
// xyz allocted here
// do something with xyz
//release xyz
example:
-(void)abc{
xyz=[[NSString alloc]init];//this may not be what you are following, but i just meant allocating memory
// do something with xyz
[xyz release]
//release xyz
In this case you need not release it in the dealloc method.
Also not that if you are property declaring xyz and retining it, you should not allocate it in your methods nor should release
while([xyz retainCount]==0)
[xyz release];
Should be > 0, otherwise the -release is not executed. Even so, deallocating xyz like this is a bad practice because xyz may be still owned by someone else.
You should allocate xyz one and only one time, and if you -copy it to replace xyz, always -release the old one. Always follow the Cocoa memory management rule.
If you really need to adopt multiple ownership to xyz, and a separate integer ivar to record how many times you have retained xyz, so you have the correct number to -release in -dealloc.

Two iPhone memory management questions

I have two questions.
1) Which of these will release ob?
- (void){
ClassOne *ob = [[ClassOne alloc] init]; // should I use autorelease here?
self.O = ob;
[ob release]; // is this correct ??
}
or
-(void)dealloc{
[O release]; // is this correct?
}
2) There are two classes, ClassOne and ClassTwo. A method in ClassTwo is:
- (void) takeParam:(ClassOne *pt) {
// something going here
}
and there is method in a third class
- (void) runIt {
ClassOne *ob = [[ClassOne alloc] init];
[classTwoOb takeParam:ob];
}
Where should I call release for the ClassOne object?
The -release method only reduces the retain count of the object in question. When the retain count reaches zero, the runtime will call -dealloc.
If at any time you send an alloc, copy, or retain message you must later call release or autorelease.
For more details see this excellent answer.
Number 1 is probably correct.
ClassOne *ob = [[ClassOne alloc] init]; // do i should use autorelease here ?
When you call [ClassOne alloc] you get an object with a retain count of 1 and you are responsible for the release.
self.O = ob;
Assuming self.O is a retain property and not an assign property, self.O/ob will have a retain count of 2.
[ob release];
Now self.O/ob will have a retain count of 1. This release matches up with the alloc. The remaining retain count is owned by self so you'll have to remember to release O when self is finished with it.
-(void)dealloc{
[O release]; // is this correct ??
}
Good. You remembered to release O. Now O will be fully released when self is dealloced. (Note: you should call [super dealloc] at the end of dealloc.)
- (void) runIt {
ClassOne *ob = [[ClassOne alloc] init];
[classTwoOb takeParam:ob];
}
You should release ob after calling takeParam:. Methods are responsible for retaining objects they want to keep. If takeParam: stores ob on classTwoOb, it should be retained before the method returns. If not, it shouldn't.
Use autorelease in methods that return objects that they have created. This gives the caller a chance to retain the object if it wants it, or not if doesn't need it for long. The exception to this is methods used to create objects, which should always be called alloc, new, or *copy*, and should return the object with a reference count of 1, making the caller responsible for the release.
To really learn Objective-C memory management, I recommend reading the Memory Management Programming Guide, especially the section on Memory Management Rules.

Why should I write [anView release], anView = nil; rather than [anView release];?

Somewhere I was reading that - regarding low memory warnings and giving up an non-visible view with all it's subviews (= a whole nib, I think), you should do that:
-(void)dealloc {
[anView release], anView = nil;
[someImageView release], someImageView = nil;
[super dealloc];
}
rather than
-(void)dealloc {
[anView release];
[someImageView release];
[super dealloc];
}
What's the reason for grounding those pointers to nil (= "no object"), after I call release? Let me guess: Some other method could have -retain'ed the view for some reason (anyone any example for when this could happen?), then the didReceiveMemoryWarning thing happens, and you release a whole nib+view that's currently not visible (i.e. in a multiview-app). As soon as the user wants to see that view again, you would quickly load the nib again and then: It loads all views, connects the outlets, and BANG! Your other retain'ed view's are hanging now without any pointer somewhere lonely in the memory brick, causing a fat and deep memory leak until your app crashes.
Right/Wrong?
The principle is more general than UIView. indeed it is more general than Objective-C/Cocoa -release method. It is valid also with C malloc()/free() memory functions.
When you no longer need an object or any memory zone, first you release/free it. Then, to make sure that you won't use it again, you clear the means to access this object or memory zone by assigning a nil to an object or a NULL to a memory pointer.
Some other method could have -retain'ed the view for some reason
Unless you're invoking dealloc yourself, it's only called when the retain count becomes zero.
Note that in Objective-C sending a message to a nil "object" is (often) perfectly fine. Doing so will not make your program halt, but the message is simply ignored. However, you cannot send a message to a freed object, which would yield a crash.
So, the following would give you an error:
[anView release];
[anView doSomething];
But, this is in fact ok:
[anView release];
anView = nil;
[anView doSomething];
It's a matter of taste, but for the above, you might in fact prefer to crash your program, rather than wondering why doSomething is not executed...
See also Sending Messages to nil from Apple's Introduction to The Objective-C 2.0 Programming Language.
The -dealloc method is called when the object is freed and no other methods on the object will be executed after. Therefore, setting any instance variable to nil has no effect outside that object.
If you were releasing an object (without using a setter) somewhere else in the class, it would be important to set the instance variable to nil to prevent code elsewhere from sending a message to that address.
I use this pattern a lot:
- (void) showHelp: (id) sender
{
if (helpController == nil)
{
helpController = [[HelpController alloc] initWithNibName: #"Help" bundle: [NSBundle mainBundle]];
}
[self presentModalViewController: helpController animated: YES];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
[helpController release];
helpController = nil;
}
Pretty much everywhere that I allocate a viewcontroller that is modal, or otherwise "temporary". This way, it hangs around if I need it again, but goes away if memory gets low.
rather than doing the expicit release and set to nil, if your accessors have properties associated with them yoc and do the following as a more concise method:
- (void) dealloc
{
self.retainedProperty1 = nil;
self.retainedProperty2 = nil;
self.copiedProperty = nil;
self.assignedProperty = nil;
}
this way you can have code that has less repetition since the synthesized code will take care of your releases for you.
Edit: i should point out that your properties can't be readonly or else you get compiler errors for obvious reasons :)