views:

373

answers:

3

In my iPhone application, I have the following line in a constructor:

self.myVar = myVar_in;

where myVar is a property and myVar_in is a parameter passed to the constructor.

When I run the code, I get an EXC_BAD_ACCESS error on this line. However, when I replace the line with:

[myVar release];
[myVar_in retain];
myVar = myVar_in;

the code runs fine. My property is declared like this: NSNumber *myVar; ... @property (retain) NSNumber *myVar;

The error is consistent and I'm positive it's not a variable scope issue. Can someone explain this behavior?

EDIT: I've confirmed that myVar_in is valid right before the line(s) are executed. Here's the actual code, although it won't help much:

-(GetAddressRequestHelper*)initWithRequest:(ClientRequest*)request delegate:(id<ServerResponseDelegate>)delegate number:(NSNumber*)myVar_in location:(CLLocation*)location {
    self = [super initWithRequest:request delegate:delegate];

    if( self ) {
        // same behavior even if this line is uncommented!!!
        myVar_in = [NSNumber numberWithInt:123];

        // prints "myVar_in is 123"
        NSLog(@"myVar_in is %@",myVar_in);       

        // doesn't throw exception
        /*[myVar release];
          [myVar_in retain];
          myVar = myVar_in;*/

        // throws exception
        self.myVar = myVar_in;

        self.location=location;
    }
    return self;
}

EDIT2: I've found I still get the behavior when I explicitly initialize the param with myVar_in = [NSNumber numberWithInt:123];!

Thanks

A: 

Try using the auto-generated setter method if you have @property and @synthesize statements for your variable. That will make sure the value of myVar_in is retained when assigned to myVar ([self setMyVar:myVar_in])

The error that you see is probably because myVar_in is released by the time you use it.

lostInTransit
self.myVar doesn't do this? I was under the impression (I'm relatively new to Objective-C) that dot notation was simply an alias for the actual explicit method call.
Jorge Israel Peña
@Blaenk is correct, the dot syntax is just a pretty way to call the property's getter/setter, whether the method is synthesized or not.
Quinn Taylor
A: 

Make sure myVar_in is actually initialized. Would you mind posting the code where you initialize myVar_in and call the initializer method?

Jorge Israel Peña
If myVar_in is an instance variable, lack of initialization shouldn't cause problems in some cases but not others. After all, the code that works does pretty much the same thing as the synthesized setter would do. Still, setting a breakpoint at the call site wouldn't hurt...
Quinn Taylor
I know you know I'm pretty new to objective-c, but he said "myVar_in is a parameter passed to the constructor", as far as I know, that doesn't count as an instance variable, but tell me if I'm wrong. Yeah, the code does the same thing as the property, which makes this weird! Hope we figure out an answer soon. I can't help but think it might have to do with `myVar_in`, since the 'manual' code that works supposedly does the same thing as the property.
Jorge Israel Peña
Quinn Taylor: The question itself says that `myVar_in` is a parameter to the initializer method.
Peter Hosey
Blaenk: You are not. You are correct.
Peter Hosey
+1  A: 

One critical difference between this code:

[myVar release];
[myVar_in retain];
myVar = myVar_in;

and this code:

self.myVar = myVar_in;

is the use of self to call the method (setMyVar).

Almost certainly your object has been incorrectly created/allocated and self is a random value (in which case the assignment of myVar = myVar_in is scribling over random memory).

Post the code showing your object creation/init call and for good how measure how myVar_in gets its value. Also post your init code (you can (very carefully) delete extraneous code, but since this is a weird case, any extraneous code might well be relevent...

Peter N Lewis
Now I feel like an idiot; my superclass initialize method omitted the line "return self". I miss Java :(
brainfsck
brainfsck: You should get a warning from the compiler for that (“control reaches end of non-`void` function”).
Peter Hosey
I do, but it's drowned out by the useless "warning: local declaration of 'someVariable' hides instance variable" warnings. I've given up asking how to disable them because I'm inevitably given a swarm of "Variable scope is a very dangerous thing! Don't even THINK about disabling that warning!!! Apple knows best!" replies.
brainfsck
getting rid of those warnings is simple, brainfsck, just name your local variables and your instance variables differently. Those compiler warnings aren't useless; ignoring them is.
Graham Lee
Eeek. Those warnings aren't useless! You really want to pare your warnings down to the ones that are due to documented problems with the compiler and/or libraries. Trust me on this -- I've been developing for 20 years, and I *often* jump without a parachute -- but on this one, Apple is right -- DO NOT ignore the warnings.
Amagrammer
brainfsck: The problem is not so much the warning sites as the sites that don't have warnings. If you forget to declare the local variable in a method, you may access the instance variable there by accident. If you name the local and instance variables differently, you won't have that problem.
Peter Hosey