Re: NSMutableDictionary problems - I think
Re: NSMutableDictionary problems - I think
- Subject: Re: NSMutableDictionary problems - I think
- From: James Spencer <email@hidden>
- Date: Sun, 20 Feb 2005 13:19:23 -0600
On Feb 20, 2005, at 10:35 AM, Raymond wrote:
I am wrapping up a language dictionary program that keeps dying after I try and add or delete more than one word at a time. You can download a copy of it from http://www.silenttrace.com/phd/objc/objcindex.html and then choose "Dictionary." so that you can take a look at what I am doing (Xcode project).
As a test choose "Just me" for dictionary when you run it and add one word. Watch the word count change and then try adding another word - that's where it crashes. Before I forget you must download the sample plist file and place it in your ~/Library/Application Support/languageDictionary/ folder which if it doesn't exist you must create. I am hoping for some feedback from more experienced cocoa coders into what I did wrong or hosed up and thus causing the problems. I am doing this mainly for a learning experience and so thanks to any of you who offers help. (A word to look up is "scusi" or try adding your own.) - I will later add the feature of doing lookups ir-regardless of capitalization.
For now I am thinking that when I add a word to the dictionary I update it back to the saved file, I am wondering if I should only do that when I go to load in a new dictionary and just leave the one that is loaded as is till i close out the program or again load a new library.
There's a lot wrong all over the place and you need to learn to use the debugger to start swatting this stuff. Specifically, if you had used the debugger and simply set a breakpoint on -[NSException raise] you would have discovered that this crash has absolutely nothing to do with NSMutableDictionary. Rather, it is crashing the second time through when you try to add the "/" to your pathToDictionary string and that this is happening because pathToDictionary is invalid when you come back through again.
My superficial examination of the code shows that this is occurring because you don't retain the pathToDictionary following the final assigment when you call pathToDictionaries = [pathToDictionaries stringByDeletingLastPathComponent]; This assigns an autoreleased NSString object to pathToDictionaries which, of course, is disposed of the next time through the event loop. Then the next time you use pathToDictionaries, BOOM.
You can stop this crash by retaining pathToDictionary before you exit addNewWordToExistingDictionary (although you have the same problem in deleteWordFromDictionary and heaven knows where else). But this merely masks the real problem which is a pretty serious misuse of memory management at least with respect to your strings. You are leaking these references to pathToDictionary like a sieve. First you create an empty NSString with
pathToDictionaries = [[NSString alloc] init];
called in firstTimeSheetDidEnd. Then you reassign a new string with
pathToDictionaries = @"/Library/Application Support/languageDictionary";
or the alternatives in the if clause. The original empty string object is now inaccessible but it was created with alloc so it will not go away until you release it which you no longer can do. Later with all of your creation of new versions of the string adding /temp to it and then retaining it, it looks like you leak this string again.
This all leads to two suggestions:
1) First, for all of your applications: USE ACCESSORS TO ACCESS INSTANCE VARIABLES. Here, your accessors for pathToDictionaries should look like
//===========================================================
// pathToDictionaries
//===========================================================
- (NSString *)pathToDictionaries { return [[pathToDictionaries retain] autorelease]; }
- (void)setPathToDictionaries:(NSString *)aPathToDictionaries
{
if (pathToDictionaries != aPathToDictionaries) {
[pathToDictionaries release];
pathToDictionaries = [aPathToDictionaries copy];
}
}
(Thanks to Kevin Callahan for Accessorizer which makes this pretty easy.) Note that the code for assigning a new value to pathToDictionaries takes care of releasing the old value and by using copy retains the new value.
2) Specific to this program, why in heavens name are you adding bits to pathToDictionaries and then taking it off over and over again. Just do:
NSString *pathForTemp = [pathToDictionaries stringByAppendingPathComponent:temp];
...
[output writeToFile: pathForTemp atomically:YES];
or even simpler:
[output writeToFile: [pathToDictionaries stringByAppendingPathComponent:temp] atomically:YES];
In either version, pathToDictionaries is left alone and the string passed to writeToFile is autoreleased so you don't have to mess with it.
Finally, I note that your code for handling clicks on the Edit button does not seem to be right: you have to click Edit twice before the Add button is enabled. If this is what you intend, it seems counterintuitive.
Spence
James P. Spencer
Rochester, MN
email@hidden
"Badges?? We don't need no stinkin badges!"
_______________________________________________
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