So i have this complex class , and i want to have an 2d array of complex numbers this is part of the code not all the code
class Complex {
public:
/* construction/destruction */
Complex(double r, double i) { this->r = r; this->i = i; }
Complex() { r=0.0; i=0.0; }
~Complex() { r=0.0; i=0.0; }
/* operations */
Complex operator+(Complex &c) { return Complex( r+c.r, i+c.i ); }
double r, i;
};
int main()
{
const int HEIGHT = 256;
const int WIDTH = 256;
Complex G[HEIGHT][WIDTH];
}
so the line Complex G[HEIGHT][WIDTH]; is the line that causes the problem , any idea why ?
Visual studio defaults to 1MB stack size, it looks like:
Complex G[HEIGHT][WIDTH];
will be just about 1MB, you can modify this using /F and the document says (emphasis mine):
Without this option the stack size defaults to 1 MB. The number argument can be in decimal or C-language notation. The argument can range from 1 to the maximum stack size accepted by the linker. The linker rounds up the specified value to the nearest 4 bytes. The space between /F and numberis optional.
The most obvious alternative would be to use dynamic memory allocation via new or std::vector.
Visual Studio as far as I know actually has one of the smaller default stack sizes:
platform default size
=====================================
SunOS/Solaris 8192K bytes
Linux 8192K bytes
Windows 1024K bytes
cygwin 2048K bytes
Mac OS X 8192K bytes
Any idea why?
Some compilers default the stack size to 1MB. You are allocating 65536 Complex
objects that occupies 2 * sizeof(double)
memory each. Assuming double
to be 8 bytes (this information is implementation defined) you are effectively trying to allocate 16 * 65536 bytes (without considering possible paddings), which are 1048576 bytes, that causes the overflow.
An alternative is using dynamic allocation with a wrapper, that simulates a bi-dimensional array indexing, along the lines of this one:
template<std::size_t A, std::size_t B>
class G {
private:
std::unique_ptr<Complex[]> mem;
public:
G() : mem(new Complex[A * B]) {}
Complex& operator()(std::size_t a, std::size_t b) {
return mem[a * B + b];
}
Complex operator()(std::size_t a, std::size_t b) const {
return mem[a * B + b];
}
};
Then you program simply becomes:
int main(int, char*[]) {
G<256, 256> g;
g(0, 0) = ...;
}
Of course you can generalize your wrapper G
for a generic type with templates, but that's outside the scope of this answer.
On a side note, you destructor:
~Complex() { r=0.0; i=0.0; }
is useless. Don't re-initialize memory that will be destroyed anyway when it leaves the scope.