'Why is my array pointer overflowing the stack?
My C++ program has a very large const array, which should be allocated on the heap, but for some reason it's crashing my stack. It goes something like this:
Foo.h
#pragma once
#include <vector>
struct Data
{
short id;
std::vector<short> points;
Data(short i, std::vector<short> p) : id(i), points(p) {}
}
class Foo
{
private:
short id;
std::vector<Data> data;
public:
Foo(short i, std::vector<data> d) : id(i), data(d) {}
};
ARRAY.h
#pragma once
#include "Foo.h"
const int ARRAY_LENGTH = 1058;
static const Foo *ARRAY = new Foo[ARRAY_LENGTH]
{
Learnset(1, std::vector<Data>({
Data(1, std::vector<short>({151, 489, 435, 65, 282, 355, 92})),
Data(8, std::vector<short>({286})),
Data(19, std::vector<short>({595})),
Data(26, std::vector<short>({417, 201})),
[...]
})),
[...]
}
This array basically serves as a database for the program. I know it's this array causing the overflow because if I comment out most of it, the program runs just fine.
Even stranger is that, when I check using sizeof, the program reports that the array is 4 bytes long, just like I would expect it to be, so I think that the program might be trying to build the array on the stack before moving it to the heap, and I'm not sure if my use of vectors is responsible. I have no idea how to correct it.
Solution 1:[1]
The reason why this is causing a stack overflow is because the initializer list for the constructor of vector<Data> is going to be constructed on the stack.
When you initialize a namespace-scope static variable, the compiler is going to emit an initialization routine that initializes the variable. In this case, you're using operator new[] and providing values with which to initialize the array (I assume Learnset should be Foo). In order to construct the Foo objects the array is initialized with, the routine will have to call the constructor of Foo, passing the arguments you provide. Those arguments, in turn, will have to be constructed first (on the stack).
So just to initialize the first element of the array, the compiler will have to create the initializer list of shorts for the vector (on the stack), construct the vector (on the stack), pass this to the constructor of Data, do this for every Data object to create the initializer list, then call the vector constructor, etc... This produces an enormous initializer list that lives on the stack, before it's passed to the constructor of vector<Data>.
If you're on a truly stack-constrained platform, you may need to make your constructors constexpr or avoid initializing by initializer list, which can consume stack space proportional to its size.
However, why are you using a pointer to dynamically allocate the array instead of just using an array type? If you use std::array<Foo, ARRAY_LENGTH> or even Foo ARRAY[ARRAY_LENGTH], the array will just live in the data segment instead of being dynamically allocated. It might even be compile-time evaluated if your constructors are constexpr. If it's not compile-time evaluated, the stack consumption is still a concern.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | colavitam |
