1

So I am now rewriting my fortran code in C (to use CUDA), and apparently I do not understand how to properly use malloc and pointers. I am trying to make the main function just calls to other functions, which need to malloc arrays that will then be used inside other functions. So, I am passing pointers of pointers to them as per this post: C Programming: malloc() inside another function

But the right amount of memory is not being allocated so I get segmentation faults. Here is the code:

    #include <stdio.h>
    #include <stdlib.h>
    //#include <cuda.h>
    #include <math.h>
    //#include "cublas.h"


    //datatype to match FORTRAN complex type
    typedef float real;

    typedef struct{

        int nx;
        int ny;
        int nz;
        int sz;
        int tz;

    } states;

    void set_SPB(real **,int,states **,states **,int **);
    //void set_SPB();
    int find_minimum(int a[], int n,int start);
    const real hc =197.32697,pi=3.1415927;
    int main(){

        int nmax = 2, A = 28;

         real *etemp, *fock;
         int *Ndex,*lookup,*lookup_a;

         states *channel,*SPB;


        //!generates the single particle basis to be used
        set_SPB(&etemp,nmax,&SPB,&channel,&Ndex);  

        free(etemp);
        free(Ndex);
        free(SPB);

        return 0;
    }
    void set_SPB(real **etemp,int nmax,states **SPB,states **channel,int **Ndex){

         int tot_orbs = (2*nmax+1)*(2*nmax+1)*(2*nmax+1)*4;
         int D = tot_orbs/4;
         int Nalpha =  (2*nmax+1)*(2*nmax+1)*(2*nmax+1)*9;
         real E;

         *etemp = (real*)malloc(D);
         *Ndex = (int*)malloc(D*3);
         *SPB = (states*)malloc(tot_orbs);
          printf("orbits without spin degeneracy %d \n",D);
          printf("size of etemp %ld \n",sizeof(*etemp)/sizeof(*etemp[0]));
          return;
         int i = 0;
        for(int nx =-nmax;nx<=nmax;nx++){
             for(int ny =-nmax;ny<=nmax;ny++){
                 for(int nz =-nmax;nz<=nmax;nz++){
                     E = 0.5*4.0*pi*pi*(nx*nx+ny*ny+nz*nz);
                     //printf("%d\n",i);
                     *etemp[i] = E;
                     *Ndex[0*D+i] =nx;
                     *Ndex[1*D+i] = ny;
                     *Ndex[2*D+i] = nz;
                     i+=1;

                  }
              }
         }

         return;
       }

Also I am not sure exactly if my assignments of the arrays are correct. Specifically the print to find the number of elements of that have been allocated always gives 2, when it should be D = 125.

Community
  • 1
  • 1
PSchwartz
  • 13
  • 3
  • If you want to use CUDA, you should rewrite it in C++, not C. – too honest for this site May 03 '16 at 01:24
  • What makes C++ more useful? The object-orientation? I do not have any experience with it, unfortunately. – PSchwartz May 03 '16 at 01:43
  • 1. You don't malloc enough space. The argument to malloc is number of bytes, not number of elements. 2. `sizeof(*etemp)/sizeof(*etemp[0])` is not useful information. `sizeof` on a pointer means how many bytes that pointer uses to potentially store the address of a block that it might point to (NOT how many bytes are allocated in such a block currently). 3. `*etemp[i]` should be `(*eTemp)[i]` and similarly for Ndex. 4. check whether `malloc` failed. – M.M May 03 '16 at 04:45
  • @PSchwartz: CUDA is **based** on C++, not C. C and C++ are different languages. Identical syntax can have different semantics. Starting with C and hoping for the best lateron is not a good idea. – too honest for this site May 03 '16 at 10:22

1 Answers1

1

I cannot believe that float and int take only 1 byte in your environment. Multiply the size to be allocated by size of their elements.

*etemp = malloc(sizeof(**etemp) * D);
*Ndex = malloc(sizeof(**Ndex) * D*3);
*SPB = malloc(sizeof(**SPB) * tot_orbs); /* not sure because this is not used */

Note that they say you shouldn't cast the result of malloc() in C.

Also note that [] operator has higher precedence than * operator, so you have to use parentheses to use the arrays.

(*etemp)[i] = E;
(*Ndex)[0*D+i] =nx;
(*Ndex)[1*D+i] = ny;
(*Ndex)[2*D+i] = nz;
Community
  • 1
  • 1
MikeCAT
  • 73,922
  • 11
  • 45
  • 70
  • That makes it run, and I believe store things correctly. However, I do get a "*** Error in `./a.out': double free or corruption (!prev): 0x0000000001379010 *** Aborted" which goes away once I comment out the free() commands. – PSchwartz May 03 '16 at 01:45
  • The sizeof(*etemp)/sizeof(*etemp[0]) still returns 2 as well. – PSchwartz May 03 '16 at 01:46
  • Sorry nevermind. I didn't make all the changes at once as I should have. Apologies for any confusion - Thank you very much. – PSchwartz May 03 '16 at 01:50
  • `sizeof(*etemp)/sizeof(*etemp[0])` is not a valid way to know the allocated size. – MikeCAT May 03 '16 at 01:51