memory management issue?
-
Hi,
I'm still pretty new to Cocoa and have just learned the hard way about
memory management. My app keeps dying in the function below. I've
gone back and cleaned up my classes according to the Memory Management
Rules (http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Tasks/
MemoryManagementRules.html#/
/apple_ref/doc/uid/20000994), but it doesn't seem to help. The first
and second time that this function gets accessed it works, no
problem. The third time it gets called it dies at:
array = [moc executeFetchRequest:request error:&error];
I put a breakpoint in right before it, and all the variables appear to
be in line. I've been stuck on it for a couple weeks now, so if anyone
has any suggestion of how I can better debug it, I'd really appreciate
it.
The error message that I get is: Program received signal:
“EXC_BAD_ACCESS”.
And here is the function:
- (void) getSelectedBuyer:(NSString*)uid
{
NSManagedObjectModel *mom = [self managedObjectModel];
NSManagedObjectContext *moc = [self managedObjectContext];
NSEntityDescription *buyerEntity = [[mom entitiesByName]
objectForKey:@"Buyer"];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:buyerEntity];
NSPredicate *predicate = [NSPredicate predicateWithFormat: @"active =
YES AND uid = %@", uid];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *array;
array = [moc executeFetchRequest:request error:&error];
if ((error != nil) || (array == nil)) {
NSLog(@"Error while fetching\n%@",
([error localizedDescription] != nil) ? [error
localizedDescription] : @"Unknown Error");
exit(1);
}
NSEnumerator *buyerEnumerator = [array objectEnumerator];
[buyer release];
buyer = [buyerEnumerator nextObject];
[buyer setAddressBook];
}
Thanks,
Steven -
On Feb 1, 2008, at 11:13 AM, Steven Crosley wrote:
> Hi,
>
> I'm still pretty new to Cocoa and have just learned the hard way
> about memory management. My app keeps dying in the function below.
> I've gone back and cleaned up my classes according to the Memory
> Management Rules (http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Tasks/
MemoryManagementRules.html#/
> /apple_ref/doc/uid/20000994), but it doesn't seem to help. The
> first and second time that this function gets accessed it works, no
> problem. The third time it gets called it dies at:
>
> array = [moc executeFetchRequest:request error:&error];
>
> I put a breakpoint in right before it, and all the variables appear
> to be in line. I've been stuck on it for a couple weeks now, so if
> anyone has any suggestion of how I can better debug it, I'd really
> appreciate it.
>
> The error message that I get is: Program received signal:
> “EXC_BAD_ACCESS”.
>
Have you tired releasing the fetch request at the end of the function
instead of autoreleaseing it?
Have you tired using NSZombiesEnabled? http://www.cocoadev.com/index.pl?NSZombieEnabled
Adhamh -
Hey Adhamh,
I did try releasing it at the end of the function, but same result. I
haven't looked at NSZombiesEnabled, I'll try that. Thanks for the
quick response.
Steven
On Feb 1, 2008, at 11:25 AM, Adhamh Findlay wrote:
>
> On Feb 1, 2008, at 11:13 AM, Steven Crosley wrote:
>
>> Hi,
>>
>> I'm still pretty new to Cocoa and have just learned the hard way
>> about memory management. My app keeps dying in the function
>> below. I've gone back and cleaned up my classes according to the
>> Memory Management Rules (http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Tasks/
MemoryManagementRules.html#/
>> /apple_ref/doc/uid/20000994), but it doesn't seem to help. The
>> first and second time that this function gets accessed it works, no
>> problem. The third time it gets called it dies at:
>>
>> array = [moc executeFetchRequest:request error:&error];
>>
>> I put a breakpoint in right before it, and all the variables appear
>> to be in line. I've been stuck on it for a couple weeks now, so if
>> anyone has any suggestion of how I can better debug it, I'd really
>> appreciate it.
>>
>> The error message that I get is: Program received signal:
>> “EXC_BAD_ACCESS”.
>>
>
> Have you tired releasing the fetch request at the end of the
> function instead of autoreleaseing it?
>
> Have you tired using NSZombiesEnabled? http://www.cocoadev.com/index.pl?NSZombieEnabled
>
> Adhamh
-
On 02/02/2008, at 4:13 AM, Steven Crosley wrote:
> [buyer release];
> buyer = [buyerEnumerator nextObject];
You're not retaining buyer. Where do you do that?
- Chris -
Thanks for all the suggestions. I changed the function based on them,
and now it dies the fifth or sixth time I access it, but on the third
time I get a more friendly error message:
[NSCFString valueForProperty:]: unrecognized selector sent to instance
0x1b90e0
So at least there's progress. Thanks again!
Steven
- (void) getSelectedBuyer:(NSString*)uid
{
NSAssert( uid != nil, @"Should have gotten a uid");
NSManagedObjectContext *moc = [self managedObjectContext];
NSAssert( moc != nil, @"What, no MOC?");
NSEntityDescription *buyerEntity = [NSEntityDescription
entityForName:@"Buyer" inManagedObjectContext:moc];
NSAssert( buyerEntity != nil, @"Should have gotten an entity");
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:buyerEntity];
NSPredicate *predicate = [NSPredicate predicateWithFormat: @"active =
YES AND uid = %@", uid];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *array;
array = [moc executeFetchRequest:request error:&error];
if ((error != nil) || (array == nil)) {
NSLog(@"Error while fetching\n%@",
([error localizedDescription] != nil) ? [error
localizedDescription] : @"Unknown Error");
exit(1);
}
NSEnumerator *buyerEnumerator = [array objectEnumerator];
[buyer release];
buyer = [[buyerEnumerator nextObject] retain];
NSLog(@"%@", [buyer uid]);
[buyer setAddressBook];
}
On Feb 1, 2008, at 11:46 AM, Chris Suter wrote:
>
> On 02/02/2008, at 4:13 AM, Steven Crosley wrote:
>
>> [buyer release];
>> buyer = [buyerEnumerator nextObject];
>
> You're not retaining buyer. Where do you do that?
>
> - Chris
>
-
On Feb 1, 2008, at 10:29 AM, Steven Crosley wrote:
> [NSCFString valueForProperty:]: unrecognized selector sent to
> instance 0x1b90e0
Sounds like a message sent to a deallocated object, something that
using NSZombieEnabled would help you troubleshoot. Give it a try!
j o a r -
Looks like it was an issue with the setAddressBook function. Works
like a charm now, and I think I more fully understand how memory
management works. Thanks again for all your help!
Before suggestions:
- (void)setAddressBook
{
book = [ABAddressBook sharedAddressBook];
person = (ABPerson *)[book recordForUniqueId:[self uid]];
}
After suggestions:
- (void)setAddressBook
{
[book release];
[person release];
book = [[ABAddressBook sharedAddressBook] retain];
person = (ABPerson *)[[book recordForUniqueId:[self uid]] retain];
}
On Feb 1, 2008, at 12:51 PM, j o a r wrote:
>
> On Feb 1, 2008, at 10:29 AM, Steven Crosley wrote:
>
>> [NSCFString valueForProperty:]: unrecognized selector sent to
>> instance 0x1b90e0
>
>
> Sounds like a message sent to a deallocated object, something that
> using NSZombieEnabled would help you troubleshoot. Give it a try!
>
> j o a r
>
>
-
On 1 Feb 2008, at 19:33, Steven Crosley wrote:
> Looks like it was an issue with the setAddressBook function. Works
> like a charm now, and I think I more fully understand how memory
> management works. Thanks again for all your help!
>
> Before suggestions:
>
> - (void)setAddressBook
> {
> book = [ABAddressBook sharedAddressBook];
> person = (ABPerson *)[book recordForUniqueId:[self uid]];
> }
>
>
> After suggestions:
>
> - (void)setAddressBook
> {
> [book release];
> [person release];
> book = [[ABAddressBook sharedAddressBook] retain];
> person = (ABPerson *)[[book recordForUniqueId:[self uid]] retain];
> }
There's a big possible flaw here. What if the old and new book or
person objects are the same? You'll release the object, and if that
deallocs it, the next code will attempt to retain a dead object.
Admittedly in this particular case it's pretty unlikely, but it's good
general practice for accessor methods of all kinds.
>
>
> On Feb 1, 2008, at 12:51 PM, j o a r wrote:
>
>>
>> On Feb 1, 2008, at 10:29 AM, Steven Crosley wrote:
>>
>>> [NSCFString valueForProperty:]: unrecognized selector sent to
>>> instance 0x1b90e0
>>
>>
>> Sounds like a message sent to a deallocated object, something that
>> using NSZombieEnabled would help you troubleshoot. Give it a try!
>>
>> j o a r
>>
>>
-
Have you read the Cocoa memory management guide? It covers accessors:
<http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Articl
es/mmAccessorMethods.html#//apple_ref/doc/uid/TP40003539>
--
m-s
On 01 Feb, 2008, at 14:33, Steven Crosley wrote:
> Looks like it was an issue with the setAddressBook function. Works
> like a charm now, and I think I more fully understand how memory
> management works. Thanks again for all your help!
>
> Before suggestions:
>
> - (void)setAddressBook
> {
> book = [ABAddressBook sharedAddressBook];
> person = (ABPerson *)[book recordForUniqueId:[self uid]];
> }
>
>
> After suggestions:
>
> - (void)setAddressBook
> {
> [book release];
> [person release];
> book = [[ABAddressBook sharedAddressBook] retain];
> person = (ABPerson *)[[book recordForUniqueId:[self uid]] retain];
> }
>
> On Feb 1, 2008, at 12:51 PM, j o a r wrote:
>
>>
>> On Feb 1, 2008, at 10:29 AM, Steven Crosley wrote:
>>
>>> [NSCFString valueForProperty:]: unrecognized selector sent to
>>> instance 0x1b90e0
>>
>>
>> Sounds like a message sent to a deallocated object, something that
>> using NSZombieEnabled would help you troubleshoot. Give it a try!
>>
>> j o a r
>>
>>
-
On 02/02/2008, at 7:38 AM, Mike Abdullah wrote:
>> - (void)setAddressBook
>> {
>> [book release];
>> [person release];
>> book = [[ABAddressBook sharedAddressBook] retain];
>> person = (ABPerson *)[[book recordForUniqueId:[self uid]] retain];
>> }
>
> There's a big possible flaw here. What if the old and new book or
> person objects are the same? You'll release the object, and if that
> deallocs it, the next code will attempt to retain a dead object.
> Admittedly in this particular case it's pretty unlikely, but it's
> good general practice for accessor methods of all kinds.
There is no flaw here, or at least not the flaw you're suggesting.
[ABAddressBook sharedAddressBook] should always return a valid object,
as will recordForUniqueID. Your comment would make sense if something
was being passed as a parameter but it's not in this case.
The only possible flaw I can see is if sharedAddressBook: or
recordForUniqueId: were to throw exceptions (I don't know if they do
or not, I haven't checked), in which case book and person wouldn't be
valid. The solution here would be to to set them to nil after
releasing them or you could use garbage collection instead.
- Chris



