Re: Need help tracking down memory issue
Re: Need help tracking down memory issue
- Subject: Re: Need help tracking down memory issue
- From: Charlton Wilbur <email@hidden>
- Date: Thu, 10 Mar 2005 09:49:20 -0500
On Mar 10, 2005, at 6:27 AM, Christian Schneider wrote:
James,
NSString* fingerprint = [[NSString alloc]
initWithString:[fileToConvert lastPathComponent]]; // 1
fingerprint = [[fingerprint
stringByAppendingString:@":"] stringByAppendingString:output]; // 2
[fingerprint release]; // 3
you are calling release on the object returned by [[fingerprint
stringByAppendingString:@":"] stringByAppendingString:output] which
probably will have been autoreleased, thus the crash. Use an
NSMutableString instead.
And he's also allocing the original fingerprint object, but never
releasing it.
I've added line numbers (to the right) for the sake of this discussion.
After line 1, fingerprint points at an alloc'd, init'd string. We'll
call this string S1. By the Cocoa rules, S1 must be released or
autoreleased when the program no longer needs it.
After line 2, fingerprint points at an alloc'd, init'd string that has
been autoreleased -- because stringByAppendingString is a convenience
method that by definition returns an autoreleased object. We'll call
this string S2. By the Cocoa rules, S2 is set: its retain count
matches the number of releases that will eventually be sent to it.
But line 3 sends a release message to S2, probably intending to send it
to S1. Unfortunately, the act that creates S2 causes the program to
lose track of where S1 is. And S2 is in the autorelease pool already:
so the release that it gets sent there balances the retain count it got
from being created, and the object is destroyed. But it's in the
autorelease pool, which means that later on it gets sent a release
message -- and there's no object there anymore to receive it.
There are a couple approaches to fixing this. The most obvious is to
use different variables, so that you don't lose track of S1 when you
create S2: instead of saying "filename = [[filename ....] ....]", you
say "NSString *revisedFilename = [[filename ....] ....]". Sometimes
this is also useful for other reasons (such as needing to refer to the
original string), but that doesn't seem like the case here.
Another approach is to see that S1 receives an autorelease call before
you replace it. You can do this either explicitly or through the use
of a convenience method:
NSString* fingerprint = [[[NSString alloc] initWithString:
[fileToConvert lastPathComponent]] autorelease]; // explicit
NSString* fingerprint = [NSString stringWithString: [fileToConvert
lastPathComponent]]; // convenience method
This approach would remove the need for the release call, as well.
A third way would be to use an NSMutableString, as noted above.
Charlton
--
Charlton Wilbur
email@hidden
email@hidden
email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden