Working with tridimensional arrays

Pages: 123
Hi guys, I'm working on a code which uses a 3D array, this is a modified version of another program I made with a 2D array which works perfectly up to M[500][500].
The problem is that when using big size arrays (M[10][100][100] for example) I get the return 3221225477 which is normally a memory problem.
So I get that I need to allocate the array on the heap, but I'm totally lost on that part. I looked for it and I found that you have to use new and delete, however I think I'm using them incorrectly

 
  float ***M = new float[10][100][100];


When I compile it says "Cannot convert float (*)[100][100] to float * in initialization.


Thanks for your help
Last edited on
The types when it comes to multi-dimensional arrays are stricter than that, because they depend on the sizes of the dimensions beyond the first dimension.

Although, you can just "cheat" the system by using auto:
1
2
3
4
5
auto M = new float[10][100][100];

// ...

delete[] M;

edit: added delete[]
Last edited on
1
2
3
4
5
6
7
// auto: http://www.stroustrup.com/C++11FAQ.html#auto
auto M = new float [10][100][100] {} ;

M[2][3][4] = 56.78f ;
// etc.

delete[] M ;


Thanks, I tried this:
1
2
auto M = new float[10][100][100];
M[0][0][0]=0.123;


but i receive: "M does not name a type"
and in the line of delete[]M; I get: argument given to delete, expected pointer.
I also tried this,
1
2
3
4
5
6
7
8
9
float ***M;
int f=100;
int z=10;
M = new float**[f];
for(i=0;i<f;i++)
     M[i]= new float*[f];
for(i=0;i<f;i++)
    for(j=0;j<f;j++)
         M[i][j] = new float[z];


But again memory error
Last edited on
Edited: no need for all this lines
Last edited on
asmatrix wrote:
but i receive: "M does not name a type"
Update your compiler, C++11 is almost a decade old at this point. You might just be able to compile with -std=c++11 as a compiler flag.

Your latest post is incredibly difficult for me to read. If you're running into memory errors, run your code in a debugger to see where the memory access violation is. My guess would be you're going out of bounds somewhere between lines 95 and 138. Just a guess.
Last edited on
> but i receive: "M does not name a type"

Deduction of the type from the initialiser (with auto) requires C++11.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>

int main()
{
    {
        // C++11
        
        // auto: http://www.stroustrup.com/C++11FAQ.html#auto
        auto M = new float [10][100][100] {} ;

        M[2][3][4] = 5.6789f ;
        // etc.
    
        std::cout << std::fixed << M[1][2][3] << ' ' <<  M[2][3][4] << '\n' ; 

        delete[] M ;
    }
    
    {
        // C++98
        
        float (*M)[100][100] =  new float [10][100][100] ;
        
        M[1][2][3] = 0 ;
        M[2][3][4] = 5.6789f ;        // ...
        
        std::cout << std::fixed << M[1][2][3] << ' ' <<  M[2][3][4] << '\n' ; 

        delete[] M ;
    }
}

http://coliru.stacked-crooked.com/a/2c48352c6729c22d

Consider using std::vector<> https://cal-linux.com/tutorials/vectors.html
Favour using double as the default floating point type.
Update your compiler, C++11 is almost a decade old at this point. You might just be able to compile with -std=c++11 as a compiler flag.


Deduction of the type from the initialiser (with auto) requires C++11.


Thank you guys!

I used -std=c++11 and it works, let me run some test and I will let you know.
Each real run takes almost 3 hours, but so far so good.
Last edited on
1
2
3
4
5
6
7
8
9
float ***M;
int f=100;
int z=10;
M = new float**[f];
for(i=0;i<f;i++)
     M[i]= new float*[f];
for(i=0;i<f;i++)
    for(j=0;j<f;j++)
         M[i][j] = new float[z];

The following code compiles 0 errors 0 warnings with this command:
g++ -Werror -Wall -Wextra -Wpedantic main.cpp -o main.exe

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>


int main()
{
    const int X_size = 10;
    const int Y_size = 100;
    const int Z_size = 100;

    double ***arr3d = new double**[X_size];

    for (int i = 0; i < X_size; ++i) {
        arr3d[i] = new double*[Y_size];

        for (int j = 0; j < Y_size; ++j) {
            arr3d[i][j] = new double[Z_size];
        }

    }

    for (int i = 0; i < X_size; ++i) {
        for (int j = 0; j < Y_size; ++j) {
            delete[] arr3d[i][j];
        }
        delete[] arr3d[i];
    }
    delete[] arr3d;
}

I get that I need to allocate the array on the heap
No you don't. You just need to not allocate it on the stack. Make it static:
static double M[10][100][100];
You don't need multi-dimensional array, if you can convert 3D indices into 1D indices:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <vector>

int main()
{
    int X_size = 2;
    int Y_size = 3;
    int Z_size = 4;

    std::vector<double> arr3d( X_size*Y_size*Z_size, 0 );
    for ( double e : arr3d ) std::cout << e << ' ';
    std::cout << '\n';

    for ( int z=0; z < Z_size; ++z )
        for ( int y=0; y < Y_size; ++y )
            for ( int x=0; x < X_size; ++x )
                arr3d[ z * X_size * Y_size + y * X_size + x ] = 100*z + 10*y + x;

    for ( double e : arr3d ) std::cout << e << ' ';
    std::cout << '\n';
}

The builtin array has such conversion, but for static size(s).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <vector>
using namespace std;

template<typename ARRAY> vector<ARRAY> dim( int m, ARRAY d ) { return vector<ARRAY>( m, d ); }

int main()
{
   int m1 = 10, m2 = 10, m3 = 10;
   auto M = dim( m1, dim( m2, dim( m3, 0.0 ) ) );

   for ( int i = 0; i < m1; i++ )
      for ( int j = 0; j < m2; j++ )
         for ( int k = 0; k < m3; k++ ) M[i][j][k] = 100 * i + 10 * j + k;

   cout << M[2][3][4] << '\n';
}
Hi guys, here's my update:

I used:
1
2
auto M = new float[5][505][505]{};
M[0][0][0]=0.123f;


And it works fine up to a Matrix size of 3x125x125, if I try to use a bigger matrix, i.e. 3x150x150 I get the memory error again. I thought this was the final solution but no.

Enoizat
The following code compiles 0 errors 0 warnings with this command:
g++ -Werror -Wall -Wextra -Wpedantic main.cpp -o main.exe

I used your code, and it compiles and runs, but I get the memory error if I use sizes bigger than 3x125x125. I'm trying to do 3x150x150 but no luck there.

dhayden
No you don't. You just need to not allocate it on the stack. Make it static:

Same thing here, it doesn't work for 150.

Kesikeverto
You don't need multi-dimensional array, if you can convert 3D indices into 1D indices:

I guess that code is too advance for me, hehe, I don't entirely understand it, and besides I have to work and change the value of the elements of the matrix several times (millions actually) so I'm not sure how to store those values.

Last chance
I just checked your code and I get the same, I'm starting to think there's a different problem here, since all the codes I tried work fine up to 125

I don´t know if you'd like me to show you the entire code so you can run it here.

P.S. just for curiosity I ran my code on the online editor and it does exactly the same


asmatrix wrote:
I don´t know if you'd like me to show you the entire code


As long as it fits in one post, preferably with code tags around it ... yes!!!
As long as it fits in one post, preferably with code tags around it ... yes!!!

Ok, here goes nothing....

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include<iostream>
#include<stdlib.h>
#include <vector>
#include<time.h>
#include<fstream>

#define alpha 0.15
#define itMAX 100
#define vcrit 6
#define f 126                       //Tamaño de la matriz bidimensional mxm
#define z 4                        //Profundidad de la matriz (coordenada z)
using namespace std;
template<typename ARRAY> vector<ARRAY> dim( int m, ARRAY d ) { return vector<ARRAY>( m, d ); }
int main(void)
{
int i, j, k, l, w, flag, av, d, X, Y, Z, cmax, warn;
int Cx[100], Cy[100], Cz[100], cont, Ex, Ey, Ez, ite;
int it_acum;

int m1 = 10, m2 = 300, m3 = 300;
auto M = dim( m1, dim( m2, dim( m3, 0.0 ) ) );

for ( int i = 0; i < m1; i++ )
for ( int j = 0; j < m2; j++ )
for ( int k = 0; k < m3; k++ ) M[i][j][k] = 0.1 * i + 0.1 * j +0.01* k;
//    const int X_size = 5;
//    const int Y_size = 301;
//    const int Z_size = 301;
//
//    double ***M = new double**[X_size];
//
//    for (int i = 0; i < X_size; ++i) {
//        M[i] = new double*[Y_size];
//
//        for (int j = 0; j < Y_size; ++j) {
//            M[i][j] = new double[Z_size];
//        }
//
//    }

//auto M = new float[5][505][505];
//M[0][0][0]=0.123;
//static double M[5][301][301];
float vs_crit, incr, frac;		//Matriz de Tamaño [Z][X][Y]
double long acum;

i=0; j=0; k=0; l=0; w=0; flag=0; av=0; d=0; X=0; Y=0; Z=0; cmax=0; warn=0;
cont=0; Ex=0; Ey=0; Ez=0; ite=0; vs_crit=0; incr=1; acum=0; frac=0;			//Inicialización de variables

system("cls");
srand(time(NULL));			//Inicializa la generación de numeros aleatorios.

for(i=1;i<f;i++)
	for(j=1;j<f;j++)
		for(k=1;k<z;k++)
			{M[k][i][j]=rand()%600;					//Rellena la matriz con numeros aleatorios del 0 al 5.99
			M[k][i][j]/=100;
			if(M[k][i][j]>vs_crit)
				{vs_crit=M[k][i][j];					//Compara si el valor actual es mayor al valor mas cercano 
				Ex=i;									//al critico y guarda sus coordenadas
				Ey=j;
				Ez=k;
				}
			}

ofstream out("3D_test.txt", ios::trunc);  //ofstream Escribir; ifstream Leer; fstream Leer y Escribir; 
										//ios::app para escribir al final del archivo ;
									//ios::trunc sobreescribe el archivo

do{
					//do-while para las iteraciones, se modifica la ultima linea para definir cuantas repeticiones se haran en total
	d=0;				//contador de la duración del evento de mayor magnitud, se inicializa en 0
	av=0;				//Contador de la magnitud max del evento, se inicializa en 0	
	
	incr=vcrit-vs_crit;	
	if(incr<0)warn=1;
	for(i=1;i<f;i++)	
			for(j=1;j<f;j++)		//este ciclo incrementa a toda la matriz con el valor de incr
				for(k=1;k<z;k++)
				M[k][i][j]+=incr;
		
//		cout<<"Matriz incremento: \n";
//		
//		for(i=1;i<f;i++)
//			{for(j=1;j<f;j++)
//				{
//				for(k=1;k<z;k++)
//				   {cout<<M[k][i][j]<<" "; //imprime la matriz inicial
//				   }   
//				cout<<"\t";
//				}
//				cout<<"\n";
//			}
//	    cout<<"\n"<<endl;
	do{
		flag=0;
		cont=0;
		for(i=1;i<f;i++)
			for(j=1;j<f;j++)
				for(k=1;k<z;k++)
					if(M[k][i][j]>=vcrit)
						{cont++;
						Cx[cont]=i;			//El arreglo Cx[] y Cy[] son unicamente para almacenar coordenadas locales, 
						Cy[cont]=j;			//se sobreescriben en cada vuelta
						Cz[cont]=k; 			//Cuenta cuantos 6's se generaron y guarda las coordenadas de este evento
						flag=1;				//Bandera que avisa que hubo un desborde
						if(cont>cmax)cmax=cont;
						}
		av+=cont;

		w=1;
		do{
			if(flag==1)
				{X=Cx[w];
				Y=Cy[w];
				Z=Cz[w];
							 
				
				frac=alpha*M[Z][X][Y]; 
				M[Z][X-1][Y]=M[Z][X-1][Y]+frac;
				M[Z][X+1][Y]=M[Z][X+1][Y]+frac;
				M[Z][X][Y-1]=M[Z][X][Y-1]+frac;
				M[Z][X][Y+1]=M[Z][X][Y+1]+frac;
				M[Z-1][X][Y]=M[Z-1][X][Y]+frac;
				M[Z+1][X][Y]=M[Z+1][X][Y]+frac;
				M[Z][X][Y]=0;	
			
			
				}
			w++;
			}while(w<=cont);
				
		if(flag==1)
		d++;			//cuenta la duracion del evento (cuantas veces recorrio completa la matriz)

		vs_crit=0;				//Reinicializa el valor sub critico a cero
		}while(flag!=0);

	ite++;
	
	out<<ite<<"\t"<<av<<"\t"<<d<<"\t"<<Ex<<"\t"<<Ey<<"\t"<<Ez<<endl;
	for(i=1;i<f;i++)
		for(j=1;j<f;j++)
			for(k=1;k<z;k++)
				{if(M[k][i][j]>vs_crit)
					{vs_crit=M[k][i][j];				
					Ex=i;
					Ey=j;
					Ez=k;
					}
		        }
		        

	}while(ite<itMAX);
out.close();
	
cout<<"Desbordes maximos: "<<cmax<<endl;
cout<<"valor de d: "<<d<<endl;
cout<<"valor de av: "<<av<<endl;
cout<<"Valor de warning: "<<warn<<endl;
//delete [] M;
//for (int i = 0; i < X_size; ++i) {
//        for (int j = 0; j < Y_size; ++j) {
//            delete[] M[i][j];
//        }
//        delete[] M[i];
//    }
//    delete[] M;
return 0;
	
	
	
}
Last edited on
It's incomplete? Cut'n paste error?

Also, can you fix the indentation.
So basically the parameter I change is
#define f 126
if you run it like this it will work perfectly, if you change the value of f to 151 it won't work

Edited: Sorry for the tags in spanish!! When I started I didn't imagine I had to ask for help!

And if you are wondering what this code does, it's a spring-block code or a variation of the sand pile code
Last edited on
It's incomplete? Cut'n paste error?

Also, can you fix the indentation.


Yes, it was! but now is complete.

I have no idea why it's shown like this, in my compiler looks great
> I have no idea why it's shown like this, in my compiler looks great
It's because you have a crazy mix of spaces and tabs for indentation.
1
2
3
4
5
6
7
8
9
10
11
 @out<<ite<<"\t"<<av<<"\t"<<d<<"\t"<<Ex<<"\t"<<Ey<<"\t"<<Ez<<endl;
 @for(i=1;i<f;i++)
@@for(j=1;j<f;j++)
@@@for(k=1;k<z;k++)
@@@@{if(M[k][i][j]>vs_crit)
@@@@ @{vs_crit=M[k][i][j];@@@@
@@@@ @ Ex=i;
@@@@ @ Ey=j;
@@@@ @ Ez=k;
@@@@ @}
@@        }

Each @ is a tab in your code
Each space is a space.

If you mix and match, then at some point, something somewhere will reduce your nicely formatted code to dog food.

Now is a good time to
- click the 'visible whitespace' option in your IDE
- clean up the indentation for consistency.
Pages: 123