Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

larswik

macrumors 68000
Original poster
Sep 8, 2006
1,552
11
Tonight I installed Xcode 4 on my Macbook air and I use my main machine which is 6 core 3.33 ghz to do almost all of my coding. I did a build tonight and then tested the app on my Macbook air where it crashed after pressing an NSButton. I Could not find the code problem so I installed 4 on my Macbook air and dragged the project over to the laptop. The MacBook air was processing the code differently then my tower. I ran Xcode 4 at the same time with the same break points and then took a snap shot of both machines. Image to the left is MacPro, and the image to the right is the MacBook. For now forgive my bad naming of tempValue and TempValueTwo

I send a message to another Method from with in my first Method. I pass 1 argument which is the stringValue of a textField
Code:
...
int scream;
    yourHitPoints = [yourHpTextField intValue];
    [COLOR="Red"][self convertButton:[hpTextField stringValue]];[/COLOR]
...
In the next Method the hpTextField string value is numbers and a character like 'a'. Example '12a' or '45d'. I use an If statement to check if there is a character or just numbers the NSString *tempValue is nil, it skips it.

As a test number I used int 10; which is what the sender is. The MacPro version is correct and tempValue is nil. The MacBook somehow assigns the senders value to the tempValue which is now 10 and crashes my program. Here is the whole Method
Code:
- (IBAction)convertButton:(id)sender {
    NSString *tempValue ;
    //NSString *tempValueTwo;
    
    scanLetter = [[NSScanner alloc] initWithString:[hpTextField stringValue]]; // Instantiate NSScanner for Letters and numbers
    scanNumber = [[NSScanner alloc] initWithString:[hpTextField stringValue]];
    NSCharacterSet *cSet = [NSCharacterSet characterSetWithCharactersInString:[hpTextField stringValue]]; //Convert string to an NSCharacterSet
    
    [scanLetter setCharactersToBeSkipped:[NSCharacterSet decimalDigitCharacterSet]]; //Set up the scanner to remove all numbers.
    [scanLetter scanCharactersFromSet:cSet intoString:&tempValue]; //Read in teh cSet and place them into the NSString
   [COLOR="Red"] if (tempValue != nil) {
        [critTextField setStringValue: tempValue];[/COLOR]
    }
 
    critValue = [self findCritValue:tempValue]; //converts letter to number or 0 if no match.
    if (critValue == 0) {
        // tempValueTwo = [NSString stringWithFormat:@"%d",0];
        [critTextField setStringValue:@""];
    }
    
    [scanNumber scanInt: &hpStorage]; // Scans in the numbers.
    [scanLetter release];
    [scanNumber release];
}

I did solve the problem by initializing NSString tempValue to nil. But how 10 got assigned to tempValue I have no idea.
 

Attachments

  • MacPro_image.jpg
    MacPro_image.jpg
    34.4 KB · Views: 182
  • MacBook_image.jpg
    MacBook_image.jpg
    36.2 KB · Views: 140
Nothing in the documentation of scanCharactersFromSet:intoString: says that it will set tempValue to nil if it doesn't scan any characters.

The correct way to determine if it has scanned anything or not is to check the BOOL return value, which will be YES if any characters where scanned or NO if none were scanned.

Additionally if you want tempValue to be nil in the case of no characters having been scanned, you'll need to explicitly code that.

Code:
    //Read in the cSet and place them into the NSString
    if ([scanLetter scanCharactersFromSet:cSet intoString:&tempValue]) {
        [critTextField setStringValue: tempValue];
    } else {
        tempValue = nil;
    }
 
You relied on the contents of uninitialized variable. With an uninitialized variable, there is no guarantee at all what results you will get. That's the same for C , C++ and Objective-C whatever compiler and operating system you use.
 
So even though I am working with String variables it is good practice to initialize them first?

But the real odd thing with the code is that the argument that I passed in and watching the debugging process with a line break for every line. The argument was assigned to tempValue before it even reached this code.

Code:
[scanLetter scanCharactersFromSet:cSet intoString:&tempValue];
But that was only true with 1 computer and not the other which my photos show. I'm sure the problem is due to my still mew experience to proper coding syntax.

But here is the other odd thing. I have no memory leaks when I test it on the laptop but it finds 2 leaks with the same code on my Desktop.

weird.

Thanks
 
Regardless of there type, (local) variables need to initialised. Otherwise you get was just happens to be in the register or memory location that compiler has assigned them.

Let's say the compiler optimised tempValue into register 6. Let's say in the calling method, the compiler uses register 6 to calculate [hpTextField stringValue] before pushing it onto the stack (or move into a another register) to pass it as the sender parameter. Then you'd observe that tempValue seems to have been assigned to sender even before a single line of your method has executed. But it's just a coincidence.

I know it doesn't go towards explaining why you see different behaviour in 2 core scenario verses a 6 core scenario. I don't want to try to reason through that because you're dealing in the realm of undefined behaviour by using an uninitialised variable. I feel that any theorisation would be futile.
 
Thanks Jim. I did not know that I needed to Initialize the variables before for local vars. I will start that habit now that I have seen what happens.

Thanks for the explanation!

-Lars
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.