I have a program that is reading data from large arrays, I initially divided the program in two separate projects in Visual Studio and each one separately worked fine, but when I tried to put them together the program acted funny skipping some steps while debugging. I'm very new on C++ so I started doing some research and I found that maybe I was filling the stack with those huge arrays and that I should try to put them on the heap instead.
I decided to change each of the arrays for a std::vector
and initialize them this way:
std::vector<double> meanTimeAO = { 0.4437, 0.441, 0.44206, 0.44632, 0.4508, 0.45425,...}
But after changing all of the arrays now when I try to compile the compiler crashes with a stack overflow, I thought I was liberating memory space from the stack by changing the arrays as a vector but it seems I had the opposite results, why is that??
and how should I deal with these big arrays? (they are fixed never changing values or size)
There is a myth that for run-time speed, one should use arrays. A std::vector can never be faster than an array, as it has (a pointer to the first element of) an array as one of its data members. But the difference in run-time speed is slim and absent in any non-trivial program.
std::vector typically allocates memory on the heap (unless you override this behavior with your own allocator). The std::vector class abstracts memory management, as it grows and shrinks automatically if elements are added or removed.
Vectors are efficient and flexible. They do require a little more memory than arrays, but this tradeoff is almost always worth the benefits.
Vector is better for frequent insertion and deletion, whereas Arrays are much better suited for frequent access of elements scenario. Vector occupies much more memory in exchange for managing storage and growing dynamically, whereas Arrays are a memory-efficient data structure.
As @Ajay's answer and @Cornstalks comment correctly point out you can avoid the stack and the heap entirely by using a static
or constexpr
qualifier on your array
const static std::array<float, 1000000> a1 = {}; // OK
constexpr std::array<float, 1000000> a2 = {}; // OK in C++11 onwards
This stores the array in the data initialized section of your memory (good explanation here). The const
serves only to disallow modification of a1
, and is not needed to avoid stack overflow. Variables declared as constexpr
are also automatically const
and hence do not need the qualifier.
Note: You can also achieve the effects of static
by making your array(s) global variables, although I would not recommend this.
If your data is non-static you should use std::vector
(or other kinds of heap allocated memory) when the number of elements is very large.
std::array<float, 1000000> a = {}; // Causes stack-overflow on 32-bit MSVS 2015
std::vector<float> v(1000000); // OK
This is because the default stack size is ~1MB, and 1 million floats requires ~4MB. The size of the heap is limited by your system's available memory (RAM). More on the stack and heap here.
The downsides of std::vector
are that it's a little slower than std::array
(heap memory allocation, deallocation and access is all slower than that of the stack), and that it's not a fixed size. However you can declare your std::vector
as const
to prevent yourself (or someone else) from accidentally altering its size or elements.
const std::vector<float> v = {...};
Now as to why your std::vector
s are causing stack overflows is a bit of a mystery. However while std::vector
allocates its elements on the heap, it also allocates a pointer (4 Bytes on 32-bit and 8-Bytes on 64-bit) on the stack. So if you have over ~250,000 std::vector
s all in scope at once, this will also cause a stack-overflow (or ~125,000 on 64-bit systems).
The compiler, like any program, allocates memory - some of which will be on the stack. The official error for a compiler stack overflow on MSVC is Fatal Error C1063.
Given that your debugger is behaving oddly, my advice would be to try and isolate the problematic code by manually splitting your code up into modular units and compiling them individually. It's possible that a small amount of code could be responsible for the error, by eating up lots of stack e.g. by recursively generating a large number of functions.
Alternatively, it may be that your code is so inherently complicated that it naturally requires more memory than the stack has. In which case, splitting your code up will still be of benefit but you could also try increasing the default stack size of MSVC.
To improve your code you could try splitting your data up into chunks. For example you could: read in ~256 KB worth of the array, process it, write the array back to file, then move onto to the next 256 KB. You could further choose the size of the chunk to be less than the size of your L1 cache (so it could all be stored at once) which would improve performance by minimizing cache misses.
MSVS 2015 (update 2) produces an internal compiler error when compiling
#include "stdafx.h"
#include <array>
int main()
{
constexpr std::array<int, 1000000> a = {};
return 0;
}
The static const
variant works fine, and if I move a
outside main (making it a global variable) then it also works fine.
Not having a chkstk.asm is unusual. Mine is located at
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\crt\src\i386\chkstk.asm
. If you're missing it, then maybe try reinstalling MS Visual Studio.
If the array is of fixed size, and its elements don't change, there is no real need to use vector
. You could use std::array
, array of const
or constexpr
instead.
constexpr float meanTimeAO[] = { 0.4437f, 0.441f, 0.44206f, 0.44632f, 0.4508f, 0.45425f,...}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With