0

I have global 3D arrays defined as

double*** arr;  

in a file common.c

I have the declaration

extern double*** arr;  

in a file common.h

Now when I am initializing this array dynamically at runtime, I am running into a segmentation fault I executed the code

 exs =malloc(sizeof(double)*nx*ny*nz);  

where nx,ny and nz are known at runtime prior to executing this statement.

But when i try to initialize this array as

  for(i=0;i<nx;i++)  
      for(j=0;j<ny;j++)  
          for(k=0;k<nz;k++)  
              arr[i][j][k]=0.0e0;  

I get a segfault.

What am I doing wrong ?

3
  • 4
    off-by-one error? your for loops should have < instead of <= Commented Jun 28, 2013 at 6:49
  • 5
    You don't have a 3D array, you have a pointer to pointer(s) to pointer(s) to int(s). You need to malloc at every level. Commented Jun 28, 2013 at 6:50
  • @TaylorFlores Corrected the code Commented Jul 1, 2013 at 11:48

2 Answers 2

7

You need to allocate all dimensions:

arr = malloc(sizeof(*arr) * nx);
for (int i = 0; i < nx; i++)
{
    arr[i] = malloc(sizeof(**arr) * ny);
    for (int j = 0; j < ny; j++)
    {
        arr[i][j] = malloc(sizeof(***arr) * nz);
        for (int k = 0; k < nz; k++)
        {
            arr[i][j][k] = 0.0;
        }
    }
}

And of course don't forget to free all the data you allocated.

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

3 Comments

@TaylorFlores Fortunately I did. :P
@JoachimPileborg Better say malloc(sizeof(*arr)) instead of an explicit type, it's safer in case the base type of the pointer changes.
Would it be possible to use calloc to get the zeros right at init time?
6

First of all, arrays are not pointers.

Second, let me show you another solution which tries to avoid memory fragmentation and uses one single call to the malloc() function (which is expensive):

double (*arr)[ny][nz] = malloc(sizeof(*arr) * nx);

After this, you can use arr as an array of dimensions nx * ny * nz.

And if you want this to be used at file scope: declare it as void *, allocate memory for nx * ny * nz elements, then assign it to a pointer-to-array when used for convenience:

// common.h
extern void *ptr;

// common.c
ptr = malloc(sizeof(double) * nx * ny * nz);

// foo.c
double (*arr)[ny][nz] = ptr;

But if you need such a hack... you should be thinking about what you have done wrong. Well, in this case, you've done wrong one thing: you are using a global variable. Don't use it.

4 Comments

@TaylorFlores Thanks. (I hope also for the one-malloc approach.)
Looks nicer - too bad that this declaration cannot be global or extern when ny and nz are not constant.
@Armali Yes, that's why one should declare it as double *ptr, then convert it to double (*)[ny][nz] at usage-time.
@Armali But anyway, why does OP use a global variable at all?

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.