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];
}
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
seanlth
  • 55
  • 1
  • 5
  • 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. – bbum Oct 24 '12 at 22:54

2 Answers2

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.

paddy
  • 60,864
  • 6
  • 61
  • 103
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.

Community
  • 1
  • 1
Bradley M Handy
  • 603
  • 6
  • 15
  • 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. – bbum Oct 24 '12 at 22:52
  • 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. – Bradley M Handy Oct 25 '12 at 02:12