Search code examples
cmemorymemory-managementheap-corruption

Corrupted Heap - C


I keep getting the following error message when I run my code in debug.

Windows has triggered a breakpoint in Linear Equations 331.exe.

This may be due to a corruption of the heap, which indicates a bug in Linear Equations 331.exe or any of the DLLs it has loaded.

Then it comes up with a break/continue.

The code uses a Gauss-Siedel Iterative method to solve a n x n system of linear equations. In this case I need to find the total amount of stretch (X) for 3 bungee cords in series,with 3 people (A,B,C) attached to it. Each solution has a different permutation of the people attached (i.e. A,B,C ; A,C,B ; B,A,C etc.)

We were supplied with a memory allocation header file called alloc.h, though I don't fully understand how it works which may be causing my problem. It worked fine before I started using ALLOCATE() for more variables. Any help in explaining why this is happening would be really helpful.

The main code is first. Header Files are at the bottom. Sorry if the code is a bit messy. I tried to comment as best as I could:

#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_WARNINGS


#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "allocate.h"
#include "iter.h"

void position_solve(int n,int k,double X[], double x[],double order[]);
void inverse(int n, double A[],double X[],double b[]);
void swap(double *,double*);
void permute(int n, double a[]);
int noofpermutations();
void next(int n,double a[]);
void permutation(int n, double a[]);
int count = 0;

int main(void) 
    {
int i,j,k,num=0, n=3, p=noofpermutations(n);
    double *A = NULL, *m = NULL, *X = NULL,* b= NULL,*K=NULL, *x=NULL, *order=NULL,   *length=NULL;

/* Allocate the required memory */
ALLOCATE(A, double, n * n);
ALLOCATE(m, double, n * p);
ALLOCATE(b, double, n);
ALLOCATE(x, double, n * p);
ALLOCATE(K, double, n * p);
ALLOCATE(X, double, n);
ALLOCATE(order,double, n);
ALLOCATE(length,double,1);


/*Defining the Order of A,B,C jumpers where 1 = A, 2 = B, 3 = C*/
printf("+-----------------------------------------------------------------------------+\n");
printf("The Order of Bungee Jumpers A,B and C is represented by \n1,2,and 3 respectively. \n");
printf("\n+-----------------------------------------------------------------------------+\n");

for(i=0;i<n;i++){
    order[i] = i+1;
    b[i] = 0;
}

length[0] = 0;
/*Hardcoding k(spring constant),x(initial length of each bungee cord) and m(mass in kg) for 3 bunjee jumpers*/
K[0] = 50;
K[1] = 100;
K[2] = 50;

m[0] = -60*9.81;
m[1] = -70*9.81;
m[2] = -80*9.81;

x[0] = 20;
x[1] = 20;
x[2] = 20;

for(i=3;i<n*p;i++){
K[i] = 0;
m[i] = 0;
x[i] = 0;
}

/*Generate Permutations of K,m for the given Order of Bungee Jumpers */
permutation(n,K);
permutation(n,m);
permutation(n,order);

/*Calculate A matrix*/
for(k=0;k<p;k++){
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            if(i==j){
                A[i*n + j] = -K[k*n + i] - K[k*n + j];
            }
            else if(j == (i+1)){
                A[i*n+j] = K[k*n + j];
                A[j*n+i] = K[k*n + j];
            }
            else if(j>(i+1)){
                A[i*n + j] = 0;
            }
        }
    }

    printf("\nFor a Bungee Jumper order %1.0lf %1.0lf %1.0lf :\n",order[k*n],order[k*n+1],order[k*n+2]);

    /*Determine multiple X (stretch of bungee in m) vecotrs*/
    /*Extract a single RHS vector (from B) into b*/
    for(i=0;i<n;i++){
        b[i]= m[k*n + i];
    }
    /*Perform Iterative Method*/
    iter_solve(n, A, b, X);

    /* Output X solutions*/
    printf("\nX = [\n");
    for (j = 0; j < n; j++) {
            printf("%f ", X[j]);
        printf("\n");
    }
    printf("]\n");
    /*Determine Order of Jumpers*/
    position_solve(n,k,X,x,order);

    printf("--------------------------------------------\n\n");

    /*If A,B,C Permutation find inverse*/
    if(((int)(order[k*n])==1) && ((int)(order[k*n+1])==2)){
        inverse(n,A,X,b);
    }
}
/* Free allocated memory */

FREE(A);
FREE(b);
FREE(x);
FREE(X);
FREE(order);
FREE(length);
FREE(m);

return 0;
}

void iter_solve(int n, double A[], double b[], double x[])
{
int i, j, k = 0;
double sum, delta = 0.2, x_store;

/*Check for division by zero and guess X=Zeros*/
for(i=0;i<n;i++){
    x[i] = 0;
    if(fabs(A[i*n + i]) < ZERO){
        //exit if division by zero occurs
        printf("Division by zero occurs. Preconditioning A matrix may be required.");
        exit(EXIT_FAILURE);
    }
}

/*Perform Gauss-Seidel Iteration*/
while( (delta>TOL) && (k<MAX_ITER) ){
    for(i = 0; i < n; i++){
        x_store = x[i];
        sum = 0;
        /*Sum for j<i*/
        for(j = 0;(j < i); j++){
            sum += A[i*n +j]*x[j];
        }
        /*Sum for i>j*/
        for((j=i+1);j<n;j++){
            sum += A[i*n +j]*x[j];
        }
        //Determine X value for current iteration
        x[i] =  (b[i]- sum)/A[i*n + i];

        /*Find the residual difference using L1-norm*/
        if((k>0) && (delta>((fabs(x[i] - x_store)/fabs(x[i]))))){
            delta = fabs(x[i] - x_store)/fabs(x[i]);
        }
    }
    k++;
}
/*Print Number of iterations*/
printf("\nNumber of iterations: %d using a tolerance of %f \n",k,TOL);
}

void position_solve(int n,int k,double X[], double x[],double order[])
{
int j, position;
double length = 0;
for (j = 0; j < n; j++) {
            //printf("%f ", X[j]);
            position = (int)(order[k*n +j]);
            length += X[j] + x[position]; 
            printf("Bungee Jumper %i: %lf meters\n",position,length);
            /*Reset X vector to zero*/
            X[j] = 0;
        printf("\n");
    }
} 

void inverse(int n, double A[],double X[],double b[])
{
int i,j;
double *Inv_A;
ALLOCATE(Inv_A, double, n * n);

for(i=0;i<n;i++){
    for(j=0;j<n;j++){
        if(i==j){
            b[i]=1;
        }
        else{
            b[i]=0;
        }
    }
    iter_solve(n,A,b,X);
    for(j=0;j<n;j++){
        Inv_A[i*n +j] = X[j];
    }
}
printf("\nInverse A = [\n");
for(i=0;i<n;i++){
    for(j=0;j<n;j++){
        printf(" %lf ",A[i*n +j]);
    }
    printf("\n");
}
printf(" ]\n");
FREE(Inv_A);
}
void swap(double *p1,double *p2)
{   double temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}

int noofpermutations(int n)
{   int permutations=1,i;
for(i=1;i<=n;i++)
permutations=permutations*i;
return permutations;
}

void next(int n,double a[])
{   int i;
for(i=0;i<n;i++){
if(count < noofpermutations(n)){
    a[(count+1)*n + i] = a[count*n +i];
} 
}
count++;
}

void permute(int n, double a[])
{   int j;
while(count<noofpermutations(n)){
for(j=0;j<n-1;j++)
{  swap(&a[count*n + j],&a[(count*n) + (j+1)]);
next(n,a);
}
swap(&a[(count*n)],&a[(count*n) + 1]);
next(n,a);
for(j=n-1;j>0;j--)
{  swap(&a[(count*n)+ j],&a[(count*n) + (j-1)]);
next(n,a);
}
swap(&a[(count*n) + (n-1)],&a[(count*n) + (n-2)]);
next(n,a);
}
}

void permutation(int n,double a[])
{
permute(n,a);
count = 0;

allocate.h

/*
 * allocate.h
 *
 * Dynamic memory allocation macros
 */

 #ifndef _allocate_h_
 #define _allocate_h_

#include <stdio.h>
#include <stdlib.h>

#define ALLOCATE(VAR,TYPE,SIZE) \
  { \
 (VAR) = (TYPE *) calloc ((SIZE), sizeof(TYPE)); \
 if ((VAR) == NULL) { \
  fprintf (stderr, "ALLOCATE: Memory allocation failed (%s:%d) [%d]\n", __FILE__, __LINE__, (SIZE)); \
  exit (EXIT_FAILURE); \
} \
  }


 #define FREE(VAR) \
{ \
free ((VAR)); \
(VAR) = NULL; \
}

#endif

/*
 * iter.h
 *
 * Routine for solving square systems of linear equations with
 * multiple right-hand sides AX=B using Gauss-Seidel iterative methods
 */


/* Zero tolerance for double precision */
#define ZERO 1.0E-12

/* Tolerance for iteration relative change */
#define TOL  0.01

/* Maximum number of iterations */
#define MAX_ITER 500

void iter_solve(int n, double A[], double b[], double x[]);
/*
 * Iterative solver, x = (b - LU * xp) / D
 * Input:
 *   n   = size of matrix A
 *   A   = factorised A matrix, (nxn) stored by row
 *   b   = right-hand side vector, (nx1)
 * Output:
 *   x = solution vector, (nx1)
 * Failure scenarios:
 *   Division by "zero"
 */


Solution

  • When his error occurs in the debugger, it should tell you where you are in the program that it occurs - hopefully this will let you identify which memory location is being corrupted.

    Note that address, restart the program in the debugger, set a breakpoint for after the allocations occurs, then set a data breakpoint on that memory location and run to see who's trashing it.