1

I'm making a 3D array in this way:

#define P 1000 int 

SPACE3D[P*2][P*2][P*2];

but I get the following compile error:

Error 1 error C2148: total size of array must not exceed 0x7fffffff bytes

Can i do something to avoid this error?

I tried also to initialize the 3D array like this:

int SPACE3D[P*2][P*2][P*2]={0};

In this way I don't have building error, but the program craches.

Any suggestions?

Tomas Aschan
  • 58,548
  • 56
  • 243
  • 402

4 Answers4

3

You need to create the array on the heap, using new or malloc(), not on the stack as you are doing. For example:

int* SPACE3D = new int[P*2*P*2*P*2];

Now you'll need to index into it using arithmetic. If you prefer a more natural, and perhaps safer, interface, there are plenty of matrix classes available outside the standard library. Please do not use a vector-of-vector-of-vectors, though, as that is very inefficient if your matrix is actually rectangular (i.e. not jagged/sparse).

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
2

You should allocate large chunks of memory on the heap instead of the stack:

int array[2*P][2*P][2*P]; // placed on the stack
int* array = new int[8*P*P*P]; // placed on the heap
vector<int> array(8*P*P*P); // vector uses heap storage

On the stack you are basically limited to some megabytes of memory, while on the heap you have a good share of you computer RAM (e.g. several GB) available.

Just keep in mind: a 3D array of 1000*1000*1000 ints requires 4 GB of memory!

Additionally I would suggest to build a small class for your 3D array:

template<typename K>
class Array3D
{
public:
    Array3D(int size) // beware, data is not initialized!
    : size_(size), data_(size*size*size) {}
    int size() { return size_; }
    size_t index(int x, int y, int z) const {
        return x + size_*(y + size_*z);
    }
    K& operator(int x, int y, int z) {
        return data_[index(x,y,z)];
    }
private:
    size_t size_;
    vector<K> data_;
};

You can use it like that:

Array3D arr(1000);
arr(12,43,745) = 15;

This snippet is missing a lot of useful features, but it shows the basic principles of how to build a 3D array. Either build upon something similar, or use one of the libraries out there.

In my opinion, in C++ I would always use a data type for arrays (1D, 2D, ...) to store the array memory and the array size together and to provide at least some kind of boundary information.

Danvil
  • 22,240
  • 19
  • 65
  • 88
  • I would strongly recommend against implementing your own multidimensional array. There are numerous well tested implementations available. – Joe Mar 27 '14 at 13:31
  • For example, the ever-popular Boost has `multi_array`. – chris Mar 27 '14 at 13:32
  • Using boost is even better! – Danvil Mar 27 '14 at 13:34
  • Even though boost is great, this code snippet is great from educational perspective. – tgmath Mar 27 '14 at 13:37
  • @tgmath: Thanks, that was my intend :) – Danvil Mar 27 '14 at 13:37
  • Aspiring programmers should be educated to use existing libraries and not fall prey to NIH syndrome – Joe Mar 27 '14 at 13:40
  • I would say they should first understand why to use a datatype. In this question the OP wanted to use a bare array. So my first advice would be: Don't do it, use a datatype, because you have to compute the correct element index. After that, the second step would be to look for a good existing implementation. – Danvil Mar 27 '14 at 13:46
  • Yes and no. If by datatype you mean data structure, yes programmers should know what data structures are appropriate. But both the original and your version are different implementations of the same data structure (a 3D array). The indexing is similar, except that with the native arrays the arithmetic is hidden. So really it is about limitations of the model used by most C++ compilers (in fact with segmented stacks and 64 bit the original could be possible on some compilers!), and that is not what you describe. Maybe I'm just being pedantic. – Joe Mar 27 '14 at 13:59
  • Sorry, but even using an existing class, Will I always have the same problem? is not my array is not gonne be too large? –  Mar 27 '14 at 14:55
  • I updated my question. You ask for 4GB of memory. This is definitely to big for the stack. Using the heap it should work if your computer has enough RAM (e.g. 8 GB). – Danvil Mar 27 '14 at 15:28
2

Lets get at this problem from a non-technical side: as you named your array "space" I will assume you want to depict space. A whole lot of nothingness and a few planets. Maybe a few spaceships. Let it be a lot of planets and a lot of spaceships. At 10 planets with 10 ships each, we are at 110 units.

With your array, you describe 1000x1000x1000 units. Most of them empty. Nothing.

In real life, you don't do it that way either. If someone asks you where the elephants are in your city, you will probably say "there are 4 in the zoo". You will not go "there's none in my room, there's none in the next room, there's none in the room after that, there's none in the room above mine, there is none in the room next to the one above mine, there is none in the kitchen, there is none on the street...".

You mention where elephants are, which implies that there are none in the other places. Doing otherwise would be an enormous waste of time and paper.

So that's the way to go in your program. Make a list of stuff that exists. If you have nothing in your list of existing things that's at [1, 56, 784], then this implies there is nothing. That way, as long as you have a list of existing spaceships, there is no limit to your universe. Not even 1000x1000x1000.

nvoigt
  • 75,013
  • 26
  • 93
  • 142
1

Allocating a 3d array that way allocates it on the stack, and it looks like it's too large.

To see how to allocate it on the heap, see this answer: C++ Multi-dimensional Arrays on the Heap

Specifically, in your case:

#define P 1000
typedef int SPACE2D_t[P*2][P*2];

SPACE2D_t* SPACE3D = new SPACE2D_t[P*2];
SPACE3D[/* from 0 to P*2-1 */][/* from 0 to P*2-1 */][/* from 0 to P*2-1 */] = 42;
delete [] SPACE3D;
Community
  • 1
  • 1
tfinniga
  • 6,693
  • 3
  • 32
  • 37
  • +1 as in this case it allows for regular indexing instead of having to compute indexes. – Joe Mar 27 '14 at 13:41