1

My iPhone app keeps receiving BAD_EXC_ACCESS error after running for a while, after painful debugging I find that one of my static variables (NSPredicate to be exact) was corrupted: it still pointed to the original address, but its isa variable was reset to 0!

This totally beats me, how come the isa variable was reset to 0 ?! Any idea ?

Thanks!

Update: post the code. The code is actually from erica's ABContactHelper I changed it a little bit to use Predicate Templates to make query more efficient, so I added this function:

+ (NSPredicate*) predicateforMatchingName:(NSString*) name {
        //templateForMatchingName is a static variable I declare elsewhere
        //static NSPredicate * templateForMatchingName =nil;
    if (templateForMatchingName == nil) {
        templateForMatchingName = [NSPredicate predicateWithFormat:@"firstname contains[cd] $NAME1 OR lastname contains[cd] $NAME2 OR nickname contains[cd] $NAME3 OR middlename contains[cd] $NAME4"];
    }

    NSDictionary *sub = [NSDictionary dictionaryWithObjectsAndKeys:
                         name,@"NAME1",
                         name,@"NAME2",
                         name,@"NAME3",
                         name,@"NAME4",
                         nil];

    NSPredicate *pred = [templateForMatchingName predicateWithSubstitutionVariables:sub];
    return pred;
} 

I have thought this code is perfect "normal", templateForMatchingName is impossible to be changed after it was created. But then I find its isa variable was reset. It is not necessarily set to nil. This time I find it was reset to different value. And the weird thing is that it still pointed to the original area.

Any idea?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Qiulang
  • 10,295
  • 11
  • 80
  • 129
  • BAD_EXC_ACCESS - usually means that you try to use a released object . post your "bad" code here –  Oct 20 '11 at 16:34

3 Answers3

3

You are calling a class method that returns an autoreleased object; try adding a nested retain during instantiation, or just use alloc&init.

And yes, the pointer would point to the original address, that's why it throws that exception. If the pointer was set to nil it would have instantiated your object again due to the if statement.

NJones
  • 27,139
  • 8
  • 70
  • 88
2

Probably the object was released and its memory reused at some point. Try it with the Zombies instrument and see. And now that you've posted your code, I see this is indeed the case. The predicateWithFormat: method returns an instance you don't own, which is liable to be released after the current autorelease pool's life is up. You need to retain it if you want to keep it around (and release the object if you reassign the variable).

Chuck
  • 234,037
  • 30
  • 302
  • 389
  • It is a static variable. And it still pointed to the original address, just it's ias was reset. I run out of solution :( – Qiulang Oct 21 '11 at 03:47
  • @Qiulang: Nothing you said there has anything to do with the object being released. Static variables don't normally cause the things they point to to become immortal, and an object being released won't cause pointers to that address to become reassigned to a new address. – Chuck Oct 21 '11 at 04:14
  • @Qiulang You should have tried it; The code you posted has a memory issue which zombies would have caught. (+1 for both answers) – justin Oct 21 '11 at 04:15
  • @NJones: No worries. I think we both posted at about the same time, and it's not like there's anything wrong with saying the same thing as somebody else anyway. – Chuck Oct 21 '11 at 04:28
  • OP, Your first comment on this answer shows your cofusion. Static variable just means class variable. So yes the class is to have a variable called temp.. And you left that pointer pointing to the address temp... Even after the autoreleased object you stored there was deallocated, because you did not retain it. That is why when you looked at where the object's ISA was you got what you thought was garbage but was really whatever was living there now. – NJones Oct 21 '11 at 04:32
0

Thanks guy! That's exactly the reason; after I retain my object the problem was solved. I think I confused with the static variable and the underlying data it pointers to.

BTW, for others who may be interested in the problem, you can refer to this as well, Why retain a static variable?

Another lesson learned here is that whenever isa variable is reset, it means the memory that object process has been reclaimed.

Community
  • 1
  • 1
Qiulang
  • 10,295
  • 11
  • 80
  • 129