</font><blockquote><font size="1" face="Geneva, Verdana, Arial, sans-serif">quote:</font><hr /><font size="1" face="Geneva, Verdana, Arial, sans-serif">Originally posted by seppak:
<strong>This is my first time using threads so I am probably doing this all wrong but anyway...
_NSAutoreleaseNoPool(): Object 0xc6220 of class NSCFString autoreleased with no pool in place - just leaking
I am writing a simple checkers program and I want the computer to think in the background so I call
[NSThread detachNewThreadSelector:@selector(chooseMoveFromGa me

toTarget:opponent withObject:game];
ChooseMoveFromGame in turn calls another function which call other functions and so on. First, I had my GameController class be an observer of NSThreadWillExitNotification so I could update the game with the move choosen. This resulted in some autoreleased arrays leaking everytime the computer moves. Insead of using the notification, I have chooseMoveFromGame calls the object that called it to send back the move it has decided upon. This works fine and I never have any memory leaks until the game is over and the computer wins making the final move. Then I get that error above four times. Can anyone explain this to me or suggest a better way to do this? I think my problem has to do with finding the move once the thread is complete.
GameController Class:
- (void)update

CheckersMove *)move
{
NSLog(@"GameController: Update Method Called");
[move retain];
[game update:move];
[move release];
</font><hr /></blockquote><font size="1" face="Geneva, Verdana, Arial, sans-serif">The retain and release above are spurious; you can safely remove them
</font><blockquote><font size="1" face="Geneva, Verdana, Arial, sans-serif">quote:</font><hr /><font size="1" face="Geneva, Verdana, Arial, sans-serif">
[checkersView updateWithGame:game];
if ([game winner] != -1)
[self restart]; // Problem here when it was the computer's move
else if ((opponent != nil) && ([game turn] == [opponent color])) {
[checkersView allowMove:NO];
[NSThread detachNewThreadSelector:@selector(chooseMoveFromGa me

toTarget:opponent withObject:game];
} else
[checkersView allowMove:YES];
}
Opponent Class:
- (void)chooseMoveFromGame

CheckersGame *)game
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSArray * moves = [game allMovesForColor:myColor];
[moves retain];
</font><hr /></blockquote><font size="1" face="Geneva, Verdana, Arial, sans-serif">The retain here (and the release below) are spurious as well. The object will not be deallocated until the pool is released.
</font><blockquote><font size="1" face="Geneva, Verdana, Arial, sans-serif">quote:</font><hr /><font size="1" face="Geneva, Verdana, Arial, sans-serif">
if (finalMove != nil) {
[finalMove release];
finalMove = nil;
}
</font><hr /></blockquote><font size="1" face="Geneva, Verdana, Arial, sans-serif">The if statement above is not necessary. Replace it with:
[finalMove release];
finalMove=nil;
Remember that a message sent to nil is ignored and returns nil.
</font><blockquote><font size="1" face="Geneva, Verdana, Arial, sans-serif">quote:</font><hr /><font size="1" face="Geneva, Verdana, Arial, sans-serif">
if ((moves != nil) && ([moves count] > 0)) {
</font><hr /></blockquote><font size="1" face="Geneva, Verdana, Arial, sans-serif">Using that property above, this can simply be written if ([moves count] > 0) {
</font><blockquote><font size="1" face="Geneva, Verdana, Arial, sans-serif">quote:</font><hr /><font size="1" face="Geneva, Verdana, Arial, sans-serif">
switch(type) {
case chimp:
[self chimpAI:game];
break;
case child:
[self childAI:game];
break;
case teenager:
[self teenagerAI:game];
break;
default:
[self adultAI:game];
break;
}
}
[moves release];
</font><hr /></blockquote><font size="1" face="Geneva, Verdana, Arial, sans-serif">You can remove the [moves release] above
</font><blockquote><font size="1" face="Geneva, Verdana, Arial, sans-serif">quote:</font><hr /><font size="1" face="Geneva, Verdana, Arial, sans-serif">
[delegate update:finalMove]; // Alternative to the notification
[pool release];
[NSThread exit];
</font><hr /></blockquote><font size="1" face="Geneva, Verdana, Arial, sans-serif">It's not necessary to call exit on a thread. Just let the function end, and the thread will exit.
</font><blockquote><font size="1" face="Geneva, Verdana, Arial, sans-serif">quote:</font><hr /><font size="1" face="Geneva, Verdana, Arial, sans-serif">
}</strong></font><hr /></blockquote><font size="1" face="Geneva, Verdana, Arial, sans-serif">The reason you're getting leaks is that the NSThreadWillExitNotification is being run in the thread that's ending, not in the main thread. Objects that you autorelease in the method called by that notification are thus leaking. I wouldn't be surprised if you had some synchronization issues too. There's no quick fix for that. Multithreading is extremely tricky.
-Peter