-4

I have a program that requires 3D arrays in order to do the Job.

This is the way I'm declaring the arrays:

double ***Xab,**Rab, ***Vab;

This is the way I'm making the arrays: Context: N = 4 , coordenadas = 3

Xab = malloc( N * sizeof(double));
Vab = malloc( N * sizeof(double));
Rab = malloc( N * sizeof(double));
for ( z = 0; z < N ; z++) {
  Xab[z] = (double **)malloc( N * sizeof(double));
  Vab[z] = (double **)malloc( N * sizeof(double));
  Rab[z] = (double *)malloc(N * sizeof(double));
  for ( v = 0; v < coordenadas; v++) {
    Xab[z][v] = (double *)malloc( coordenadas * sizeof(double));
    Vab[z][v] = (double *)malloc( coordenadas * sizeof(double));
  }
}

This is the way I fill the arrays:

for ( z = 0; z < N; z++) {
  for ( v = 0; v < N; v++) {
    for ( w = 0; w < coordenadas; w++) {
      Xab[z][v][w] = y[z][w] - y[v][w];
      Vab[z][v][w] = y[z][w+3] - y[v][w+3];
    }
    Rab[z][v] = sqrt( pow(Xab[z][v][0],2)+ pow(Xab[z][v][1],2) 
    + pow(Xab[z][v][2],2) );
  }
}

The problem is directly with Xab and Vab ( the 3D arrays ), everything works fine as long as N < 4, but when N > 3 I get a Segmentation fault.

I Tried to debug it ( gdb ) on OpenSuse Leap 42.1 ( x86_64 ).

Program received signal SIGSEGV, Segmentation fault. 0x0000000000405009 in PostNewtonNcuerposV2 (x=0, y=0x60a040, dvdt=0x60a4e0, M=0x60a010, N=4) at NbodyPNV2.c:34

34 Xab[z][v][w] = y[z][w] - y[v][w];


1: y[z][w] = 0

2: y[v][w] = 59165672784.100632

3: w = 0

4: v = 3

5: z = 0

6: Xab[z][v][w] = "error: Cannot access memory at address 0x0"

So I tried the following:

(gdb) display Vab[3][3][3]

7: Vab[3][3][3] = error: Cannot access memory at address 0x18

(gdb) display Vab[3][2][3]

9: Vab[3][2][3] = 6.4687520944348569e-319


So, that's the problem. the 2D arrays memory allocation works fine above N > 3 but the 2D segment of the 3D arrays doesn't, and is for all 3D arrays that i have.

I think that it might be because of the way making the arrays. While investigating i encounter a post talking about a stack overflow ( ironically ) en the OS itself, but i couldn't find any kind of solution. Every other post that i could find solves it with a correct control variable usage ( z,v,w in my case ) or with a better declaration of the arrays. In this cases the code didn't work at all, but mine does (as expected ) with N < 3.

So, the main question is the following. Is there any thing wrong with the allocation of the 3d arrays? or Is there any way the let the program access or change the memory address that is trying to use?

Any idea is appreciated.

Thank you in advance.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • 1
    `sizeof(double)` consider yourself lucky if that is at least as large as a `sizeof(double**)` or `sizeof(double*)`. You're using the wrong types for your outer dimensions. And [stop casting `malloc` in C program](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – WhozCraig Oct 18 '16 at 16:51
  • You don't have a 3D array in your code and nothing which can represent one. A 3D array is something like `double [DIMZ][DIMY][DIMX]`. Your jagged array cannot represent a 3D array, nor point to one. – too honest for this site Oct 18 '16 at 16:54
  • casting `malloc` & co, and for whatever reason using tripple indirection... Please, just don't do that. Keep in mind that `int foo[3][3][3]` and `int foo[27]` basically can be used in exactly the same way. An array is always a contiguous block of memory, 1D or 3D, it doesn't _really_ make much of a difference. you need 1 block of memory, big enough to hold `N³` double's, why not use `double *Xab = malloc(N*N*N*sizeof *Xab);`? – Elias Van Ootegem Oct 18 '16 at 16:58
  • In addition to the wrong types for `sizeof`, you are also using the wrong terminating value for your inner loop for making the arrays. I think it should be `for (v = 0; v < N; v++)`, not `for (v = 0; v < coordenadas; v++)`. – Ian Abbott Oct 18 '16 at 16:59
  • Being a 3-star C programmer is not a compliment. In far by most cases it is a signal of wrong conception. Your's included. – too honest for this site Oct 18 '16 at 17:19
  • Thank you! all of your comments and solutions not just solved my issue, but made my program go faster. – Brayan lemus Oct 18 '16 at 17:21

1 Answers1

2

You're not allocating the proper amount of memory for the array.

First, the allocations for the first dimension should be a multiple of sizeof(double **), since that's the type you're creating an array for. Similarly, the allocations for the second dimension should be a multiple of sizeof(double *).

Secondly, the range of the inner loop is not correct. Since the second dimension has N elements, you want that loop to run N times, not coordenadas times. So when N is larger than coordenadas, you don't have enough space for the elements of the second dimension.

Also, don't cast the return value of malloc, as that can lead to subtle bugs.

With the above fixes, you should now have this:

Xab = malloc( N * sizeof(double **));
Vab = malloc( N * sizeof(double **));
Rab = malloc( N * sizeof(double *));
for ( z = 0; z < N ; z++) {
  Xab[z] = malloc( N * sizeof(double *));
  Vab[z] = malloc( N * sizeof(double *));
  Rab[z] = malloc(N * sizeof(double));
  for ( v = 0; v < N; v++) {
    Xab[z][v] = malloc( coordenadas * sizeof(double));
    Vab[z][v] = malloc( coordenadas * sizeof(double));
  }
}
Community
  • 1
  • 1
dbush
  • 205,898
  • 23
  • 218
  • 273