0

I am making a curve fitting program using matrices in the form of a two dimensional arrays but the compiler throws out BAD_ACCESS errors at random such as Thread 1:EXC_BAD_ACCESS (code=1, address=0x13f800000). The program works sometimes and other times crashes. Any ideas would be appreciated. Thanks.

- (void)main {
    NSLog(@"Enter size");

    scanf("%i", &matrixSize);

    float* temp;

    matrix = (float**)calloc(matrixSize, sizeof(float*));
    temp = (float*)calloc(matrixSize+1, sizeof(float));

    for (int i = 0; i < matrixSize+1; i++) {
        matrix[i] = temp + (i*(matrixSize+1));
    }

    [self enterPoints];
    [self elimination];
    [self setNeedsDisplay:YES];
    free(matrix);
    free(temp);
}

//points entered here

- (void)enterPoints {
    CGPoint *points = (CGPoint *)malloc(matrixSize * sizeof(CGPoint));

    for (int i = 0; i < matrixSize; i++) {
        scanf("%lf", &points[i].x);
        scanf("%lf", &points[i].y);
    }

    for (int j = 0; j < matrixSize; j++) {
        for (int i = 0; i < matrixSize+1; i++) {
            if (i == (matrixSize)) {
                matrix[i][j] = points[j].y;
            }
            else {
                matrix[i][j] = pow(points[j].x, (matrixSize-1)-i);
            }
        }
    }
    free(points);
}

//matrix reduction occurs here

- (void)elimination {

    for (int j = 0; j < matrixSize; j++) {
        double divideValue = matrix[j][j];
        for (int i = 0; i < matrixSize+1; i++) {
            matrix[i][j] /= divideValue;
        }
        for (int j1 = 0; j1 < matrixSize; j1++) {
            if (j1 == j) {
                if (j1 == matrixSize-1) {
                    break;
                }
                else {
                    j1++;
                }
            }
            double subValue = matrix[j][j1];
            for (int i = 0; i < matrixSize+1; i++) {
                matrix[i][j1] -= matrix[i][j]*subValue;
            }
        }
    }
}

//drawing the polynomial 

- (void)drawRect:(NSRect)dirtyRect {
    NSGraphicsContext * GraphicsContext = [NSGraphicsContext currentContext];
    CGContextRef context = (CGContextRef) [GraphicsContext graphicsPort];

    CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);

    CGContextSetLineWidth(context, 3.0);

    CGContextMoveToPoint(context, 0, matrix[matrixSize][0]*100 + 100);

    [GraphicsContext saveGraphicsState];

    CGMutablePathRef path;

    path = CGPathCreateMutable();

    for (float i = -matrixSize; i < matrixSize; i+=.01) {
        float y = 0;

        for (int j = 0; j < matrixSize; j++) {
             y += matrix[matrixSize][j]*pow(i, j);
        }

        CGContextAddLineToPoint(context, i*100 + 100, y*100 + 100);   
    }

    CGContextStrokePath(context);

    [GraphicsContext restoreGraphicsState];
}
1
  • It is a bid odd to have a GUI program that is also parsing standard-input... Odd in that it generally doesn't work at all like you might expect. Commented Oct 24, 2012 at 22:54

2 Answers 2

1

You did not allocate enough memory for your matrix. This line sets up the entire data area, but you have only allocated matrixSize+1 elements, instead of matrixSize*(matrixSize+1):

temp = (float*)calloc(matrixSize+1, sizeof(float));

So, maintaining the matrixSize+1 columns and matrixSize rows:

matrix = (float**)calloc(matrixSize, sizeof(float*));
temp = (float*)calloc(matrixSize * (matrixSize+1), sizeof(float));

for (int i = 0; i < matrixSize; i++) {
    matrix[i] = temp + (i*(matrixSize+1));
}

When you use this later, be careful. You are addressing it wrong:

for (int j = 0; j < matrixSize; j++) {
    for (int i = 0; i < matrixSize+1; i++) {
        if (i == (matrixSize)) {
            matrix[i][j] = points[j].y;
        }
        else {
            matrix[i][j] = pow(points[j].x, (matrixSize-1)-i);
        }
    }
}

Notice that i goes to matrixSize+1 but you are using that as the row index (there are only matrixSize rows). I think you meant to use matrix[j][i] instead of matrix[i][j]. You also do this when you construct the initial matrix, but I've actually changed that to be in line with your allocation.

So there are two points of buffer overrun in your program that I see.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, my whole view of referring to elements in a matrix was wrong.
0

EXC_BAD_ACCESS indicates one of your objects is being over-released (not to be confused with garbage collection) before invoking a method on it. Once you reach the point in your code where you invoke the method on the collected object, the pointer is referencing an invalid memory location.

To find Zombie objects have a look at this: How to Enable NSZombie in XCode

I've used this and it works very well.

2 Comments

Unless this is on OS X with the garbage collector enabled, there is no garbage collector. There are many reasons why EXC_BAD_ACCESS might happen and, given that OP is mucking with malloc()d memory, it is quite likely not an over-released object.
True. I mistyped. There is no garbage collection in iOS. I haven't done much with malloc()d memory in a long time so most of my experience with EXC_BAD_ACCESS errors have been with over-released objects.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.