C ++ 3d array - dynamic memory allocation aligned on one line

I have a rather strange question that probably has no practical use, but the answers are very worrying. I tried a little chat with arrays and how to allocate them in memory using this code: (Xcode compiler 4 bits, 4 bytes integer)

int ***c; int size_x = 0; int size_y = 0; int size_z = 0; cout << "Enter x: " << endl; cin >> size_x; cout << "Enter y: " << endl; cin >> size_y; cout << "Enter z: " << endl; cin >> size_z; c = new int**[size_x]; for (int i = 0; i < size_x; ++i) { *(c+i) = new int*[size_y]; for (int j = 0; j < size_y; ++j) { *(*(c+i)+j) = new int[size_z]; } } for (int i = 0; i < size_x; ++i) { for (int j = 0; j < size_y; ++j) { for (int k = 0; k < size_z; ++k) { cout << (*(*(c+i)+j)+k) << endl; //cout << &c[i][j][k] << endl; } } } delete [] c; 

When I log in now: 3, 2, and 4, I get the following output in the console:

0x100100a60 0x100100a64 0x100100a68 0x100100a6c 0x100100a70 0x100100a74 0x100100a78 0x100100a7c 0x100100a90 0x100100a94 0x100100a98 0x100100a9c 0x100100aa0 0x100100aa4 0x100100aa8 0x100100aac 0x100100ac0 0x100100ac4 0x100100ac8 0x100100acc 0x100100ad0 0x100100ad4 0x100100ad8 0x100100adc

What is my question now, if we look at the result, than we see that basically, the memory is aligned every 4 bytes, but sometimes we see a larger step, for example, from 0x100100a7c to 0x100100a90.

This is normal and how can I prevent it? Why is this? Is there any way to make c align my memory as a constant line? (I am not native English, so I'm sorry about that, but I don't know how to say it better)

Its just for a general understanding :-)

Thanks u!

PS is it enough to use delete [] after btw or do I need to go through each of the 3 memory blocks and delete [] the whole array there? EDIT:

Now I delete the memory and this works very well:

 cout << "Free Memory" << endl; for (int i = 0; i < m_sx; ++i) { for (int j = 0; j < m_sy; ++j) { delete [] m_array[i][j]; //delete [] (*(*(m_array)+j)+k); } delete [] m_array[i]; } delete [] m_array, m_array = NULL; 
+4
source share
5 answers

The problem is not that your memory is not aligned ... the requirement of the C ++ specification for calling new and new[] is that it passes back a pointer pointing to the continuous memory, which is correctly aligned for the platform and the size of the requested object .

Your problem is that you do not allocate the entire buffer for the array with a single call to new[] , but rather with multiple calls to new[] . Therefore, when each call to new returns aligned and contiguous memory, multiple calls to new[] not required to return the memory buffers that are adjacent to each other. For example, each call to new[] returns aligned memory, but, as you noted, there may be β€œspaces” at the beginning of each memory array that new returns. The reason for these "gaps" can have several reasons and really depends on how the underlying OS allocates memory for your program.

If you do not want to have β€œspaces” in each array, you will need to allocate the entire buffer with a single call to new .

Finally, to answer your question about delete[] , yes, because you did not allocate the entire memory buffer with a single call to new[] , you cannot delete your array with a single call to delete[] . Each call to new[] must be associated with a call to delete[] , since these were separate memory allocations.

+2
source

Yes, it is normal. The memory is aligned, by the way, it just does not touch, because subsequent calls to new do not provide this guarantee. And yes, you can select the entire three-dimensional array in one adjacent buffer:

 int *A = new int[size_x * size_y * size_z]; 

or safer

 std::vector<int> A(size_x * size_y * size_z); 

and then index it with

 int element = A[i * size_z * size_y + j * size_z + k] 

to get the element in (i,j,k) .

This is actually very useful as it gives you multidimensional arrays with little overhead, while maintaining a local link and preventing indirectness. In addition, error handling for this distribution scheme is much simpler, so you run the risk of losing memory. Any good matrix library will be implemented this way. For C ++, which includes Boost.MultiArray .

Regarding the release: yes, you need a few calls to delete[] in your current schema.

+6
source

Here is a procedure that allocates a three-dimensional array of N1 x N2 x N3 dimensions in an adjacent memory space, allowing you the syntax a [i] [j] [k] for operator access. The array is dynamic, but continuous, so it represents a huge plus over the <> approach vector and new call cycles [].

 template <class T> T ***Create3D(int N1, int N2, int N3) { T *** array = new T ** [N1]; array[0] = new T * [N1*N2]; array[0][0] = new T [N1*N2*N3]; int i,j,k; for( i = 0; i < N1; i++) { if (i < N1 -1 ) { array[0][(i+1)*N2] = &(array[0][0][(i+1)*N3*N2]); array[i+1] = &(array[0][(i+1)*N2]); } for( j = 0; j < N2; j++) { if (j > 0) array[i][j] = array[i][j-1] + N3; } } cout << endl; return array; }; template <class T> void Delete3D(T ***array) { delete[] array[0][0]; delete[] array[0]; delete[] array; }; 

And later in your implementation procedure ...

 int *** array3d; int N1=4, N2=3, N3=2; int elementNumber = 0; array3d = Create3D<int>(N1,N2,N3); cout << "{" << endl; for (i=0; i<N1; i++) { cout << "{"; for (j=0; j<N2; j++) { cout << "{"; for (k=0; k<N3; k++) { array3d[i][j][k] = elementNumber++; cout << setw(4) << array3d[i][j][k] << " "; } cout << "}"; } cout << "}"; cout << endl ; } cout << "}" << endl; Delete3D(array3d); 

Gives output:

 { {{ 0 1 }{ 2 3 }{ 4 5 }} {{ 6 7 }{ 8 9 }{ 10 11 }} {{ 12 13 }{ 14 15 }{ 16 17 }} {{ 18 19 }{ 20 21 }{ 22 23 }} } 
+4
source

Since it is labeled C, there is also a C answer here. Since C99 multidimensional arrays can be processed quite efficiently, even if the dimensions are dynamic:

 double c[size_x][size_y][size_z]; 

This allocates the matrix adjacent to the stack. The matrix elements are accessed by c[i][j][k] , and the compiler does all the indexing arithmetic for you. If you fear that this could lead to SO, you can easily call malloc with it:

 double (*c)[size_y][size_z] = malloc(sizeof(double[size_x][size_y][size_z])); 
+3
source

Yes, it is normal. You select data line by line; The only thing you can be sure of is that the data will be contiguous on each row.

+1
source

Source: https://habr.com/ru/post/1379878/


All Articles