I\'m somewhat new to programming in general and I\'ve run into an issue with declaring 3D and 4D arrays. I have several declarations like this at the start of my main function,
Assuming for simplicity that sizeof(string) == 2
(it's probably more), you're trying to allocate (64^3)*9*2 bytes on the stack. That comes out to 4,718,592 bytes, or approximately 4.5 MiB. Most likely, you just don't have 4.5 MiB available on your stack.
Since these variables are declared in main()
, you have two possible solutions:
Declare them static
.
Declare them outside main()
, as global variables.
This will cause them to be allocated before the program starts, rather than on the stack. The only difference between the two approaches is whether they'll be visible in other functions.
There may also be a way to tell your compiler that the program needs more stack space, but I think making them static is probably the better solution here. If they were in a function other than main()
though, you'd probably need to do something else.
This line:
string reg_perm_mark_name[64][64][64]
declares 64*64*64 = 262144 strings on the stack. A std::string
is typically about 32 bytes so thats about 8MB. The maximum stack size is typically about 1MB.
To declare the array dynamically you could use std::vector
. Generally, multidimensional std::vector
s can be a bit cumbersome and it is often better to declare a single dimensional vector and convert to a single index when you access an element:
std::vector<std::string> reg_perm_mark_name(64*64*64);
int i = 13;
int j = 27;
int k = 7;
reg_perm_mark_name[i + 64*j + 64*64*k] = "Hello world!";
But in this case you can declare a multi-dimensional std::vector
quite efficiently by using std::array
instead of std::vector
for the inner types. The use of std::array
avoids too many memory allocations as they have a fixed size. I would use typedefs or using aliases to make the declaration clearer:
using StrArray = std::array<std::string, 64>;
using StrArray2D = std::array<StrArray, 64>;
std::vector<StrArray2D> reg_perm_mark_name(64);
reg_perm_mark_name[3][4][7] = "Hello world!";
A simple solution is to use static allocation (i.e. move your arrays outside of any function, or mark them as static
).
Note that if you use C++ arrays then the usage and footprint are the same but then they behave like proper containers:
array<array<array<string,64>,64>,64> reg_perm_mark_name;
To use dynamic allocation unsafely, you could write:
auto reg_perm_mark_rot = new short[64][64][64][4];
// ...
delete[] reg_perm_mark_rot;
To use it safely, since C++14 (note that the innermost dimension gets special treatment):
auto reg_perm_mark_rot = std::make_unique<short[][64][64][4]>(64);
Of course you can use array
instead of C-style arrays with the dynamic options, but then you would have an extra level of indirection to use the array.