Exc_Bad_Access


#1

I am brand new to Objective-C iPhone and I just started the 'Quiz" iPhone app exercise which worked right off the bat as is from the book. :smiley: But then I added a bunch of NSLog statements figuring that these where the equivalent of print statements so that I could step through. The app started crashing and in the debug mode I saw that “Exc_Bad_Access” was being thrown, which according to the forums indicates bad memory management? I did not think NSLog would cause this, it this because the memory location has changed? [NB I add “currentQuestionIndex = -1;” so that my question index would start at the first question instead of the second one when the iPhone simulator launched.]

Sample of my code changes…

//
// QuizAppDelegate.m
// Quiz
//
// Created by ronald greti on 5/16/10.
// Copyright MyCompanyName 2010. All rights reserved.
//

#import “QuizAppDelegate.h”

@implementation QuizAppDelegate

@synthesize window;

-(id)init
{
// Call the init method implemented by the superclass
[super init];

//Create two arrays and make the pointers point to them
questions = [[NSMutableArray alloc] init];
answers = [[NSMutableArray alloc] init];

// Add questions and answers to the arrays
[questions addObject:@"What is 7 + 7?"];
[answers addObject:@"14"];

[questions addObject:@"What is the capitol of Vermont?"];
[answers addObject:@"Montpelier"];

[questions addObject:@"From what is cognac made?"];
[answers addObject:@"Grapes"];

[b]NSLog(@"displaying current index value: %@", currentQuestionIndex);[/b]
[b]currentQuestionIndex = -1;[/b]

// Return the address of the new object
return self;

}

  • (IBAction)showQuestion:(id)sender
    {
    // Step to the next question
    currentQuestionIndex++;
    NSLog(@“displaying current index value: %@”, currentQuestionIndex);

    // Am I past thge last questions?
    if (currentQuestionIndex == [questions count])
    {
    // Go back to the first question
    currentQuestionIndex = 0;
    }

    // Get the string at that index in the question arrary
    NSString *question = [questions objectAtIndex:currentQuestionIndex];

    // Log the string to the console
    NSLog(@“displaying question: %@”, question);

    // Displaying the string in the question field
    [questionField setText];

    // Clear the answer field
    [answerField setText:@"???"];
    }

  • (IBAction)showAnswer:(id)sender
    {
    // What is the answer to the current question?
    NSString *answer = [answers objectAtIndex:currentQuestionIndex];

    // Log the string to the console
    NSLog(@“displaying answer: %@”, answer);

    // Display it in the answer field
    [answerField setText:answer];
    }

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // Override point for customization after application launch

    [window makeKeyAndVisible];

    return YES;
    }

  • (void)dealloc {
    [window release];
    [super dealloc];
    }
    @end


#2

EXC_BAD_ACCESS doesn’t necessarily mean you are managing memory improperly, it means you have accessed memory in a way that you are not allowed to.

Long answer: When you call NSLog, you pass it a format string (the first argument) which has a number of tokens (things prefixed with %) that get replaced with the rest of the parameters you supply to NSLog.

The order of the tokens matters: the first token will use the first argument after the format string, the 2nd uses the 2nd, and so on. Having a mismatch of number of tokens and arguments also will cause a problem (if you have more arguments than tokens, you won’t see the extra arguments, if you have more tokens than arguments, you will crash).

There are a few standard tokens from C that we have, like, %d, %i, %l, %s, etc. The character involved in the token determines how NSLog interprets the associated parameter. For example, %d will be replaced with the integer value of the associated parameter. %s will copy the bytes starting at the address held in the parameter (a pointer) until it sees NULL (or 0). This is how we print string variables in C.

Objective-C added a new token, %@. This token must be paired with an Objective-C object. The %@ token is replaced by the string returned from that Objective-C object’s description method.

If the associated parameter for a %@ token is not an Objective-C object, bad things will happen. For example, your code has associated a %@ token with an integer variable. Let’s say the integer variable is equal to 2 when this happens. NSLog will attempt to send the message to 2nd byte of memory in RAM. Of course, not only do you not know what is at byte 2 of RAM, it is not memory you can access, hence the bad access exception.

Short answer: Use %d for integers, %f for floats, %s for C strings, %@ for Objective-C objects (including NSStrings). For any other types, consult the man page for printf (open Terminal.app, type man printf).