CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com

Thread: 3D array memory allocation dimensions

1. Member
Join Date
Oct 2010
Posts
25

3D array memory allocation dimensions

Hello,

I am using this piece of code for allocating 3D array in memory by my dimensions HEIGHT, WIDTH, DEPTH, which are variables.

p2DArray = new double**[HEIGHT];
for (int i = 0; i < HEIGHT; ++i) {
p2DArray[i] = new double*[WIDTH];

for (int j = 0; j < WIDTH; ++j)
p2DArray[i][j] = new double[DEPTH];
}

My problem is this: When i have for example HEIGHT = 512, WIDTH = 512 and DEPTH = 2 my 3D allocated array has right dimension in HEIGHT and WIDTH but DEPTH dimensions are not 2, but its larger.

For example when I want to read from p2DArray[511][511][845646] it doesnt say me, that I am out of dimensions (with [845646] in DEPTH), but it will give me random number value. When I want to read on position for example p2DArray[518][511][0] it will say me, that I am out of dimension because of HEIGHT size.

Could you please tell me, why this piece of code allocates 3D array right in HEIGHT and WIDTH dimension, but false in DEPTH (it allocates a lot of bigger in DEPT dimension, than I would like)?

THANKS FOR ANY HELP!

2. Elite Member Power Poster
Join Date
Apr 1999
Posts
27,449

Re: 3D array memory allocation dimensions

Originally Posted by Kositch
Hello,

I am using this piece of code for allocating 3D array in memory by my dimensions HEIGHT, WIDTH, DEPTH, which are variables.

p2DArray = new double**[HEIGHT];
for (int i = 0; i < HEIGHT; ++i) {
p2DArray[i] = new double*[WIDTH];

for (int j = 0; j < WIDTH; ++j)
p2DArray[i][j] = new double[DEPTH];
}

My problem is this: When i have for example HEIGHT = 512, WIDTH = 512 and DEPTH = 2 my 3D allocated array has right dimension in HEIGHT and WIDTH but DEPTH dimensions are not 2, but its larger.
Show us a complete program that duplicates the error, not just a piece of code. We can't see into your computer, so there is no way we can verify your claims.

There is nothing wrong with that code (except that it is extremely inefficient).

Regards,

Paul McKenzie

3. Member
Join Date
Oct 2010
Posts
25

Re: 3D array memory allocation dimensions

Originally Posted by Paul McKenzie
Show us a complete program that duplicates the error, not just a piece of code. We can't see into your computer, so there is no way we can verify your claims.

There is nothing wrong with that code (except that it is extremely inefficient).

Regards,

Paul McKenzie
OK, thanks for reply, here is the code example with my problem:

short int ***test;

int HEIGHT = 10;
int WIDTH = 20;
int DEPTH = 3;

test = new short int**[HEIGHT]; //allocating memory for arry of size 10 x 20 x 3
for (int x = 0; x < HEIGHT; ++x) {
test[x] = new short int*[WIDTH];
for (int y = 0; y < WIDTH; ++y)
test[x][y] = new short int[DEPTH];
}

for (int z = 0; z < DEPTH; z++) //filling it with ones
{
for (int y = 0; y < WIDTH; y++)
{
for (int x = 0; x < HEIGHT; x++)
{
test[x][y][z] = 1;
}
}
}

cout << test[5][15][2]; //it will write number one, its ok
cout << test[5][15][5]; //it should say, that i am off the array size with number 5 in depth dimension (program should throw exception), but it will write some random number -21598 and doesnt throw any exception, that i am looking out of allocated memory

4. Elite Member Power Poster
Join Date
Apr 1999
Posts
27,449

Re: 3D array memory allocation dimensions

Originally Posted by Kositch
cout << test[5][15][5]; //it should say, that i am off the array size with number 5 in depth dimension (program should throw exception),
Where did you get that erroneous information from?
but it will write some random number -21598 and doesnt throw any exception, that i am looking out of allocated memory
Welcome to the world of C++ programming.

When you make a mistake such as writing outside the boundaries of an array in a C++ program, there is nothing that guarantees how your program will behave. The program may throw an exception, or it may work without anything happening, or may throw an exception when run on your machine but run without anything happening on another machine, plain old crash without an exception, etc.

C++ is not Java or C#, or some other computer language that has these checks at runtime and automatically will inform you of a problem.

Regards,

Paul McKenzie
Last edited by Paul McKenzie; October 10th, 2010 at 03:23 PM.

5. Member
Join Date
Oct 2010
Posts
25

Re: 3D array memory allocation dimensions

Originally Posted by Paul McKenzie
Where did you get that erroneous information from?Welcome to the world of C++ programming.

When you make a mistake such as writing outside the boundaries of an array in a C++ program, there is nothing that guarantees how your program will behave. The program may throw an exception, or it may work without anything happening, or may throw an exception when run on your machine but run without anything happening on another machine, plain old crash without an exception, etc.

C++ is not Java or C#, or some other computer language that has these checks at runtime and automatically will inform you of a problem.

Regards,

Paul McKenzie
Thanks for explanation, but why i am making memory allocation, when i can read from array also out of its boundaries?

So my code is right and it allocates only memory that i need?

6. Re: 3D array memory allocation dimensions

Originally Posted by Kositch
why i am making memory allocation, when i can read from array also out of its boundaries?
I assume because nobody taught you proper C++. There is really no need to manually handle dynamic arrays like you do. If you would use a std::vector<std::vector<std::vector<short> > > you would get the same effect as what your code does, but without having to manage the memory yourself. Also, you can use the vector's at member function to enforce bounds checking.

An even better solution might be to use boost::multi_array, if you are willing to learn how to use it.

7. Elite Member Power Poster
Join Date
Apr 1999
Posts
27,449

Re: 3D array memory allocation dimensions

Originally Posted by Kositch
Thanks for explanation, but why i am making memory allocation, when i can read from array also out of its boundaries?
I don't quite understand your question.

Reading and writing beyond the boundaries of an array leaves the behaviour of the program undefined. You're asking "how come I can do this in C++", and I answered already -- C++ does not check for array accesses being out of bounds.
So my code is right and it allocates only memory that i need?
There are container classes, as mentioned previously, where you do not need to handle the memory yourself. For example, std::vector.

As far as your current code goes, there are much better ways of handling the memory. Please take a look:
Code:
```double***Create3DArray(int height, int width, int depth)
{
double ***p3DArray = new double**[height];
double **data1 = new double*[height * width];
double *data2 = new double[ height * width * depth];

for (int i = 0; i < height; ++i, data1 += width)
{
p3DArray[i] = data1;
for (int j = 0; j < width; ++j, data2 += depth)
p3DArray[i][j] = data2;
}
return p3DArray;
}

void Free3DArray(double ***array3d)
{
// you fill this in to release the memory
}

int main(int argc, _TCHAR* argv[])
{
double ***myArray = Create3DArray(512, 512, 2);
myArray[0][2][4] = 59; // for example
Free3DArray(myArray);
return 0;
}```
Note that there are only 3 calls to "new", regardless of the width, height, and depth. The trick is to allocate all of the memory for the array, and then point the pointers into the pool of memory correctly. Similarly, it only takes 3 calls to "delete[]". I didn't show this to you, since this looks like a homework assignment.

As to your current code, it makes height*width + 1 calls to "new". That can seriously fragment the heap as well as slow down the creation of the array.

Imagine if the width and height were 500. You would be making 250,001 calls to "new[]", and to release the memory, you would be making 250,001 calls to delete[]. That is way too many times to be calling the allocator. But with the code I posted, it will still do just 3 calls to "new[]".

Regards,

Paul McKenzie

8. Member
Join Date
Oct 2010
Posts
25

Re: 3D array memory allocation dimensions

Originally Posted by Paul McKenzie
I don't quite understand your question.

Reading and writing beyond the boundaries of an array leaves the behaviour of the program undefined. You're asking "how come I can do this in C++", and I answered already -- C++ does not check for array accesses being out of bounds.
There are container classes, as mentioned previously, where you do not need to handle the memory yourself. For example, std::vector.

As far as your current code goes, there are much better ways of handling the memory. Please take a look:
Code:
```double***Create3DArray(int height, int width, int depth)
{
double ***p3DArray = new double**[height];
double **data1 = new double*[height * width];
double *data2 = new double[ height * width * depth];

for (int i = 0; i < height; ++i, data1 += width)
{
p3DArray[i] = data1;
for (int j = 0; j < width; ++j, data2 += depth)
p3DArray[i][j] = data2;
}
return p3DArray;
}

void Free3DArray(double ***array3d)
{
// you fill this in to release the memory
}

int main(int argc, _TCHAR* argv[])
{
double ***myArray = Create3DArray(512, 512, 2);
myArray[0][2][4] = 59; // for example
Free3DArray(myArray);
return 0;
}```
Note that there are only 3 calls to "new", regardless of the width, height, and depth. The trick is to allocate all of the memory for the array, and then point the pointers into the pool of memory correctly. Similarly, it only takes 3 calls to "delete[]". I didn't show this to you, since this looks like a homework assignment.

As to your current code, it makes height*width + 1 calls to "new". That can seriously fragment the heap as well as slow down the creation of the array.

Imagine if the width and height were 500. You would be making 250,001 calls to "new[]", and to release the memory, you would be making 250,001 calls to delete[]. That is way too many times to be calling the allocator. But with the code I posted, it will still do just 3 calls to "new[]".

Regards,

Paul McKenzie
Thanks a lot, this look better then my.

The delete part of the code will be like this?:

Code:
```	delete []  array3d**[height];
delete []  array3d*[height * width];
delete []  array3d[ height * width * depth];```

9. Elite Member Power Poster
Join Date
Apr 1999
Posts
27,449

Re: 3D array memory allocation dimensions

Originally Posted by Kositch
Thanks a lot, this look better then my.

The delete part of the code will be like this?:

Code:
```	delete []  array3d**[height];
delete []  array3d*[height * width];
delete []  array3d[ height * width * depth];```
Actually no, but you have the right idea. The first thing is that you delete in reverse order that the data was allocated.

So you delete the pool of memory first (data2). Since the start of the pool is at array[0][0], you delete this. Then you delete where data1 starts. This is at array[0]. Then last, you delete array.

Regards,

Paul McKenzie

10. Member
Join Date
Oct 2010
Posts
25

Re: 3D array memory allocation dimensions

So like that?:

Code:
```delete [] array3d[0][0]
delete [] array3d[0]
delete [] array3d```

I hope, it's right now :-) There will be needed no for cycles?
Last edited by Kositch; October 11th, 2010 at 02:03 AM.

11. Re: 3D array memory allocation dimensions

Originally Posted by Kositch
So like that?:

Code:
```delete [] array3d[0][0]
delete [] array3d[0]
delete [] array3d```
I hope, it's right now :-) There will be needed no for cycles?
Nope, you are still missing a ton of deletes. The syntax is;
Code:
`delete [] pointer;`
the keyword is "delete []", which will delete the array allocated at pointer. Note that at no point in time do you specify the size of the object to be deleted. You need one delete per allocation, so in your case:

Code:
```for (int x = 0; x < HEIGHT; ++x)
{
for (int y = 0; y < WIDTH; ++y)
{
delete [] test[x][y];;
}
delete [] test[x];
}
delete [] test;```
Just delete in the oposite order that you allocated.

EDIT: Arrays are "fun" for learning, But I highly recommend you learn to use vectors. Understanding how an array works is important, but learning to use vectors correctly is even more important.
Last edited by monarch_dodra; October 11th, 2010 at 03:20 AM.

12. Re: 3D array memory allocation dimensions

It's more dangerous to use than vector
But it looks neat: only new then delete everything seems fine after all

13. Elite Member Power Poster
Join Date
Apr 1999
Posts
27,449

Re: 3D array memory allocation dimensions

Originally Posted by monarch_dodra
Nope, you are still missing a ton of deletes.
For the code I posted, the set of three deletes are correct. For the original OP's code, your code is correct.

Regards,

Paul McKenzie

14. Re: 3D array memory allocation dimensions

Originally Posted by Paul McKenzie
For the code I posted, the set of three deletes are correct. For the original OP's code, your code is correct.

Regards,

Paul McKenzie

15. Member
Join Date
Oct 2010
Posts
25

Re: 3D array memory allocation dimensions

Originally Posted by Paul McKenzie
For the code I posted, the set of three deletes are correct. For the original OP's code, your code is correct.

Regards,

Paul McKenzie
Paul, so my second try of deleting array is now right (code is above)?

Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•