pdenlinger
pdenlinger

Reputation: 3917

Thread 1: EXC_BAD_ACCESS (code=13, address = 0x0)

Have a program which compiles, but then quits, returning the above error message.

Here is the 0 objc_msgSend log; have commented out the line the error message appears on:

libobjc.A.dylib`objc_msgSend:
0x7fff8c9b7e80:  testq  %rdi, %rdi
0x7fff8c9b7e83:  je     0x00007fff8c9b7eb0       ; objc_msgSend + 48
0x7fff8c9b7e85:  testb  $1, %dil
0x7fff8c9b7e89:  jne    0x00007fff8c9b7ec7       ; objc_msgSend + 71
0x7fff8c9b7e8c:  movq   (%rdi), %r11
0x7fff8c9b7e8f:  pushq  %rax
0x7fff8c9b7e90:  movq   16(%r11), %r10
0x7fff8c9b7e94:  movl   %esi, %eax
0x7fff8c9b7e96:  andl   (%r10), %eax           // error message arrow appears on this line
0x7fff8c9b7e99:  movq   16(%r10,%rax,8), %r11
0x7fff8c9b7e9e:  incl   %eax
0x7fff8c9b7ea0:  testq  %r11, %r11
0x7fff8c9b7ea3:  je     0x00007fff8c9b7edb       ; objc_msgSend + 91
0x7fff8c9b7ea5:  cmpq   (%r11), %rsi
0x7fff8c9b7ea8:  jne    0x00007fff8c9b7e96       ; objc_msgSend + 22
0x7fff8c9b7eaa:  popq   %rax

// Rest left out; no error messages

main.m:

#import <Foundation/Foundation.h>
#import "Budget.h"

#import "Transaction.h"
#import "CashTransaction.h"
#import "CreditCardTransaction.h"

int main(int argc, const char * argv[])
{

    Budget *europeBudget = [Budget new];
    [europeBudget createBudget:1000.00 withExchangeRate:1.2500];

    Budget *englandBudget = [Budget new];
    [englandBudget createBudget:2000.00 withExchangeRate:1.5000];


    NSMutableArray *transactions = [[NSMutableArray alloc]initWithCapacity:10];
    Transaction *aTransaction;
    for (int n=1; n < 2; n++) {

        [aTransaction createTransaction:n * 100 forBudget:europeBudget];
        [transactions addObject:aTransaction];
        aTransaction = [CashTransaction new];
        [aTransaction createTransaction:n * 100 forBudget:englandBudget];
        [transactions addObject:aTransaction];
    }

    int n = 1;
    while (n < 4) {

        [aTransaction createTransaction:n * 100 forBudget:europeBudget];
        [transactions addObject:aTransaction];
        aTransaction = [CreditCardTransaction new];
        [aTransaction createTransaction:n * 100 forBudget:englandBudget];
        [transactions addObject:aTransaction];
        n++;
    }


        for (Transaction * aTransaction in transactions) {
            [aTransaction spend];
    }


            return 0;
}

Transaction.h

import

@class Budget;

@interface Transaction : NSObject
{
    Budget *budget;
    double amount;
}

- (void) createTransaction:(double)theAmount forBudget:(Budget*) aBudget;
- (void) spend;
- (void)trackSpending: (double) theAmount;

@end

Transaction.m

#import "Transaction.h"
#import "Budget.h"

@implementation Transaction

- (void) createTransaction:(double)theAmount forBudget:(Budget*) aBudget
{
    budget = aBudget;
    amount = theAmount;
}

- (void) spend
{
    // Fill in the method in subclasses
}

-(void)trackSpending: (double) theAmount
{
    NSLog(@"You are about to spend another %.2f", theAmount);
}
@end

Upvotes: 0

Views: 8516

Answers (2)

alp
alp

Reputation: 61

I landed on this issue while I was looking for a solution to another problem around SIGSEGV.

Although it is a bit late response, I would like to answer this question for the sake of documentation and completeness.

The problems arises because you are sending messages to an object without instantiating one.

Transaction *aTransaction;
for (int n=1; n < 2; n++) {

    [aTransaction createTransaction:n * 100 forBudget:europeBudget];

and create method was defined as:

- (void) createTransaction:(double)theAmount forBudget:(Budget*) aBudget;

I would write these methods as follows.

First of all, createTransaction sounds like a factory method to me. So, I would make it a class method, like:

+(Transaction *) createTransactionWithAmount:(double) theAmount forBudget: (Budget *) aBudget;

Then I would use that factory method like below:

for (int n=1; n < 2; n++) {
     Transaction *aTransaction = [Transaction createTransactionWithAmount: n*100 forBudget: europeBudget];
   // [aTransaction createTransaction:n * 100 forBudget:europeBudget];
    [transactions addObject:aTransaction];

That should fix 2 problems with the code:

1) You will always have an instance to send messages against defined as aTransaction var
2) You don't have to worry about adding this object into the collection as it won't be nil anymore.

Upvotes: 6

davehayden
davehayden

Reputation: 3484

aTransaction isn't assigned a value when it's declared, so it starts out with a garbage value. The first time through the loop, you're sending a message to that garbage value: crash! Declaring the variable with a nil initial value will fix the problem:

Transaction *aTransaction = nil;

Upvotes: 2

Related Questions