views:

61

answers:

5

I'm stuck with the following bit of code.

NSString *gridRef = [[NSString alloc] initWithFormat: @"%@", [converter LatLongToOSGrid: latLong]];
NSLog(@"Grid Ref: %@", gridRef);
self.answerLabel.text = [[NSString alloc] initWithFormat: @"%@", gridRef];

When I log gridRef, it displays the correct result. However, the line setting answerLabel.text causes an EXC_BAD_ACCESS error and the program crashes. IB is connected to the correct label, what is the problem?

Thanks


I've updated the code as follows:

    - (IBAction)convertLatLong {
    NSArray *latLong = [[NSArray alloc] initWithObjects: latTextField.text, longTextField.text, nil];

    GridRefsConverter *converter = [[GridRefsConverter alloc] init];

    NSString *gridRef = [[NSString alloc] initWithFormat: @"%@", [converter LatLongToOSGrid: latLong]];
    NSLog(@"Grid Ref: %@", gridRef);
    NSLog(@"Label: %@", self.answerLabel.text);
    answerLabel.text = @"Yippy";
    self.answerLabel.text = gridRef;

    [gridRef release];
    [converter release];
    [latLong release];
}

answerLabel is initialised through @property @synthesize when the view controller is pushed onto the stack. (I don't know how it gets init'd apart from it's one of the magical things IB does for you. Or so I assume. I've used exactly the same method in other view controllers and have not had this issue.


I've found the culprits - the question is, how do I go about releasing them?

NSString *eString = [[NSString alloc] initWithFormat: @"%f", e];
NSString *nString = [[NSString alloc] initWithFormat: @"%f", n];
eString = [eString stringByPaddingToLength: (digits/2) withString: @"0" startingAtIndex: 0];
nString = [nString stringByPaddingToLength: (digits/2) withString: @"0" startingAtIndex: 0];
NSString *theGridRef = [letterPair stringByAppendingString: eString];
theGridRef = [theGridRef stringByAppendingString: nString];
[eString release];
[nString release];

return theGridRef;

and:

NSArray *gridRef = [[NSArray alloc] init];
gridRef = [gridRef arrayByAddingObject: [NSNumber numberWithDouble: E]];
gridRef = [gridRef arrayByAddingObject: [NSNumber numberWithDouble: N]];
gridRef = [gridRef arrayByAddingObject: [NSNumber numberWithInteger: 8]];

NSString *theGridRef = [[NSString alloc] initWithFormat: @"%@", [self gridRefNumberToLetter: gridRef]];

[gridRef release];
[theGridRef autorelease];

return theGridRef;

}

A: 

Check if asnwerLabel is actually non-null. You should also change this line:

self.answerLabel.text = [[NSString alloc] initWithFormat: @"%@", gridRef];

To:

self.answerLabel.text = [NSString stringWithFormat: @"%@", gridRef];

Otherwise, you will end up with a memory leak in that line.

Pablo Santa Cruz
A: 

Maybe the label is not inited at that point in your code, try to check it. Why are you allocating a new NSString? Just do:

self.label.text = gridRef;
[gridRef release];
rano
I have changed to code to the following: NSString *gridRef = [[NSString alloc] initWithFormat: @"%@", [converter LatLongToOSGrid: latLong]]; NSLog(@"Grid Ref: %@", gridRef); NSLog(@"Label: %@", self.answerLabel.text); self.answerLabel.text = gridRef;And NSLog output is:2010-08-28 13:38:30.078 iFly[19777:207] Grid Ref: ST551023212010-08-28 13:38:30.079 iFly[19777:207] Label: LabelProgram received signal: “EXC_BAD_ACCESS”.
churchill614
seems like the label is not printed since it is not allocated.In which method are you calling this piece of code? If you are doing this in the init method of your viewController, try to do it in the `viewDidLoad` instead
rano
A: 

how is answerLabel created? You might need to retain that. Or you possibly need to release some things (gridRef)?

I can't see any other issues with your code.

You can (and probably should) set your

answerLabel.text = gridRef;

gridRef is already an NSString, so you don't need to alloc it again.

EXC_BAD_ACCESS is usually a memory thing related to your retain/release count not balancing (or in my extensive experience of it :p).

Thomas Clayson
gridRef is released after the label gets updated. I've looked through and can't see any issues regarding releasing/retaining. If they are output correctly by NSLog, surely they have at least a retain count of 1?
churchill614
yes, but what about answerLabel? give it a value then just before you change its value NSLog(@"%@",answerLabel.text); and see if that output anything...
Thomas Clayson
+2  A: 

You should enable zombie detection by setting the environment variable NSZombieEnabled to YES, so you can see which object causes the bad access (don't forget to remove this again when you found the bug).

Also you can use Instruments to find the location where the object actually gets released. For this start a new Instruments session and use the "Allocations" instrument. In the instrument settings check "Enable NSZombie detection" and "Record reference counts". When running the session you will break where the error occurs and you see a record of all retains/releases.

One place where you can have a quick look if your object is incorrectly freed is in the -viewDidUnload method, where you should release the outlet and set it to nil. If you forget the latter and you access the outlet somehow, it will result in a EXC_BAD_ACCESS.

Edited to match your update:

The problem is that you are assigning eString (and nString) a new string which was alloc/init-ed. Then you override those in the next statements, because -stringByPaddingToLength: (as well as all the other -stringBy... methods) return a new and autoreleased string object. So you lost the reference to the old string which means that there is a memory leak. Additionally at the end you release the already autoreleased objects explicitly which causes your bad access.

Instead you should create autoreleased strings from the beginning ([NSString stringWithFormat:...]) and don't release them at the end.

frenetisch applaudierend
I'm struggling with instruments - how do I set it up, and what does the output mean?Console, with NSZombieEnabled tells me -[CFString release]: message sent to deallocated instance 0x68809e0. But how do I find out what instance has been deallocated?
churchill614
Explaining Instruments would be a bit a huge task to do here. However there was a question on SO before which should get you started: http://stackoverflow.com/questions/1554526/how-to-use-instruments-while-testing
frenetisch applaudierend
Thanks, that's clarified a lot of things for me. I'm slowly learning about the whole memory management in objC. Cheers!
churchill614
Always glad when I can help. If you didn't do so already, I recommend you read the Memory Management Programming Guide (http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html) which explains these topics in detail.
frenetisch applaudierend
A: 

Okay, the problem was trying to release NSStrings, so I've stopped doing that and the problem has been solved.

Can someone clarify how strings are retained and released. I was of the impression that:

string = @"My String"; is autoreleased. NSString *string = [[NSString alloc] init...]; is not autoreleased and needs to be done manually.

churchill614