views:

227

answers:

3

Objective-C: I need help retaining the value of an int. It's changing on me without my command.

The original question was: "How do you declare and retain an int?", that was satisfied in another post here: http://stackoverflow.com/questions/1938513

Now I have a problem where an int that was 18 is changing to 2, somehow on its own.

Here's my code:

@interface Game : Layer // this is from cocos2d
{
   int maxSprites;
}

@implementation Game
-(void)initVariables
{
  maxSprites = 18;
}

Later on, when I print it out, like

 NSLog(@" maxSprites = %d  ", maxSprites);

I get:

 maxSprites = 2

And operations that require it to be 18, crash or don't work, as if it's really just 2 now.

How would that be possible? =)

Apple + Shift + F reveals no other usage of the maxSprites variable.

I've looked at other code examples and often they're exposing the variable with a getter and setter, and they are also using @property. Am I missing something? I'm new to Objective-C, so I might as well just be!

I did a Apple + Shift + F for maxSprites" In Project, Textual, Contains, Ignore Case and only resulted in:

       Game.h:  int maxSprites;
       Game.m:  maxSprites = 18;
       Game.m:  NSLog(@" maxSprites  = %d", maxSprites);
       Game.m:  NSLog(@" maxSprites  = %d", maxSprites);
       Game.m:  NSLog(@"maxSprites is at %p", &maxSprites);
       Game.m:  NSLog(@"maxSprites is at %p", &maxSprites);
       Game.m:  NSLog(@" maxSprites  = %d", maxSprites);
       Game.m:  NSLog(@" maxSprites  = %d", maxSprites);
       Game.m:  NSLog(@"maxSprites is at %p", &maxSprites);
       Game.m:  NSLog(@"maxSprites is at %p", &maxSprites);

I found the location where it changes using a watchpoint. It changes

    Expression: “*(int *) 67379960”
    New Value: 2
    Old  Value: 18

on this line:

   [self checkMatchBarAward:spriteTypeToAdd];

Odd? That function doesn't do anything with maxSprites, nor does that line.

EDIT: here is the function, I commented everything inside it out and it still occurs: .h

    -(void)checkMatchBarAward:(int)spriteTypeToAdd;

.m

     -(void)checkMatchBarAward:(int)spriteTypeToAdd
      {
      }

EDIT:

Thanks for the recommendations. I have cleaned all targets and it still changed values. Because of the answers you guys/gals gave, you lead me to the problem. Thanks for all of your help.

I posted my results below in an answer. Here's a copy:

Guys/gals you wouldn't believe what was the cause. Thank you for all your help because telling me to clean and look and check my types, that helped.

I looked over my arrays. I found one that was declared like this:

  int matchBarArray[8];

2 lines up from the breakpoint halt where it says that the value changed from 18 to 2, I have this line:

  matchBarArray[spritesCaptured-1] = spriteTypeToAdd;

And guess what, I overstepped the bounds of the array by 1. If I increase the size of the array to 9, I no longer get the int change from 18 to 2.

Also, if I overstep the bounds by more than 1, that is, I reduce the array size to smaller, there are other things that start changing such as my score, booleans, the whole game ! =)

I can't believe hitting memory outside the array in Objective-C can cause such a riot =) AND IT'S SO HARD TO DEBUG!

A: 

I didn't see the line you specify in your code.

Chances are, though, that you are referring to something as a long* when it's an int* or something like that (although how, after all these years, C STILL can't see that is beyond me).

Anyway, check your types where the sizes of what they point to may differ. If you reference an int * memory location with a long * (say, by passing in an int* to a method that expects a long*), you will fubar the stack and start modifying adjacent variables.

I've done this more than once, but in C, not Objective C--so I'm not sure it's the correct answer.

Bill K
+2  A: 

If your checkMatchBarAward: method truly is empty, then you need to clean your project (Shift + cmd + k) and rebuild it.

Dave DeLong
+3  A: 

Guys/gals, you wouldn't believe what was the cause. Thank you for all your help because telling me to clean and look and check my types, that helped.

I looked over my arrays. I found one that was declared like this:

  int matchBarArray[8];

2 lines up from the breakpoint halt where it says that the value changed from 18 to 2, I have this line:

  matchBarArray[spritesCaptured-1] = spriteTypeToAdd;

And guess what, I overstepped the bounds of the array by 1. If I increase the size of the array to 9, I no longer get the int change from 18 to 2.

Also, if I overstep the bounds by more than 1, that is, I reduce the array size to smaller, there are other things that start changing such as my score, booleans, the whole game ! =)

I can't believe hitting memory outside the array in Objective-C can cause such a riot =) AND IT'S SO HARD TO DEBUG!

Jeremiah
Ah, the fun of C arrays. This is why many people advise avoiding them for all but very simple or highly optimized cases.
Chuck
When you declare a plain array in C, the computer sets aside enough memory to store the contents of that array, and then saves the location of the start of that memory block. That's it. When you say matchBarArray[n], it figures out what location in memory you're talking about by taking that saved memory location and adding to it (sizeof(int)*n). It neither knows nor cares whether that's within the bounds of your array. Of course, if it's out of bounds, there's no telling what you just overwrote. This isn't just Obj-C, by the way: It's C, C++ and Obj-C++ as well.
Warren Pena
Also, unless you have a very compelling reason to use plain C-style arrays, you're usually much better off using a smarter data structure, such as NSArray and friends. Those data structures have type checking that will prevent you from making silly mistakes like that.
Warren Pena
Good comment Warren. I was hoping though that by watching the variable that it would show me the actual line it happened instead of the one beneath. It wasn't very apparent. I wanted to use C arrays for the performance, since it's a game. When I did C before and didn't handle arrays properly I remember it being easier to debug.This is interesting that NSArray protects from that...
Jeremiah
You should accept your own answer. I think there's a badge for it. :)
Daniel Yankowsky
@Jeremiah: Objective-C is a strict superset of C. The C parts of it aren't just *like* C, they *are* C. This would work the same in a plain C project. The difference probably has to do with the compiler's optimization settings.
Chuck