2
votes

I'm having an issue that I cannot seem to fix with my memory allocations.

I create 3 dynamically allocated arrays (ipiv,k,b) using malloc, but when I try and free them, I get a seg fault. If I don't free them, the code works fine (but if I run too many iterations, I run out of memory).

Here is the code... I've taken out all of the parts that do not use the 3 arrays, since the code is pretty long.

#include<stdio.h>
#include <string.h>
#include<stdlib.h>
#include<math.h>
#include <mpi.h>
#include "mkl.h"

#define K(i,j) k[(i)+(j)*(n)]

void dgesv_( const MKL_INT* n, const MKL_INT* nrhs, double* a,
            const MKL_INT* lda, MKL_INT* ipiv, double* b, 
            const MKL_INT* ldb, MKL_INT* info );

int main()
{
    int *ipiv=malloc(n*sizeof(int));
    for (i=0; i<n; i++) {
        ipiv[i]=0;
    }

    for (globloop=0; globloop<=lasti; globloop++) {

        double a[ndofs];
        double rhs[ndofs];
        double F[ndofs];

        double *k=malloc(n*n*sizeof(double));


        //var for stiffness matrix (this is the one acutally fed to dgesv) 
            //see define at top
        for (i=0; i<n; i++) {
            for (j=0; j<n; j++) {
                K(i,j)=0.0;
            }
        }   

            //bunch of stuff modified, a,rhs,and F filled... ect

        while (sos>=ep && nonlinloop<=maxit) {

            double KFull[ndofs][ndofs];
            for (i=0; i<ndofs; i++) {
                for (j=0; j<ndofs; j++) {
                    KFull[i][j]=0.0;
                }
            }

                    //KFull filled with values..

            //trim the arrays to account for bcs 
            double *b=malloc(n*sizeof(double));
            for (i=0; i<n; i++) {
                b[i]=rhs[i+2];
            }

            //k array filled
                    //see define above
            for (i=0; i<n; i++) {
                for (j=0; j<ndofs-2; j++) {
                    K(i,j)=KFull[i+2][j+2];
                }
            }

            //SOLVER
            dgesv_(&n,&one,k,&n,ipiv,b,&n,&info);

            //now we must take our solution in b, and place back into rhs
            for (i=0; i<n; i++) {
                rhs[i+2]=b[i];
            }
            nonlinloop++;
            free(b);
        }
        free(k);
    }
    free(ipiv);
    return 0;
}

Freeing any one of these 3 variables gives me a segmentation fault. I am super-confused about this.

1
Run it with valgrind and it shall tell you whats wrong. - Alok Save
Is it possible that ndofs-2 is greater than n? - Sergey Kalinichenko
nope, they are specifically set to be such that n=ndofs-4. - user1864020
I know this doesn't fix your problem, but for the sake of performance I would allocate all three arrays just once outside all loops and reuse them. Their size seems independent of the iteration and you discard it at the end of each loop. You only really need dynamic memory in two cases: You intend to transfer it between function scopes or it is too big to fit on the stack. Stacks are in non-embedded systems generally 2-8Mb large. If your arrays fit on the stack I'd even place them there. - Sergey L.
Another thing: Are you sure dgesv_ doesn't already free them? Calling free on a pointer that has already been freed is normally a SIGSEGV. - Sergey L.

1 Answers

1
votes

If n=ndofs-4 (as mentioned in the OP's comment) then ndofs-2 is greater then n. And then the code will be corrupting the memory at

K(i,j)=KFull[i+2][j+2];

because j runs up to ndofs-2-1 and K is (only) defined to be K[0..n-1][0..n-1].