4

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 ?

6
  • 3
    Assuming an 8 byte double, that's 1MB of stack storage for G alone, which is typically the overall limit. Commented Nov 27, 2013 at 4:42
  • Because you're overflowing the stack with 65536 Complex objects. It's really not a ... complex ... thing to understand. Commented Nov 27, 2013 at 4:44
  • It is better not to allocate large arrays on the stack - use malloc - and maybe create an access function as part of the class in order to keep the indexing simple. Commented Nov 27, 2013 at 4:46
  • @Floris, s/malloc/vector/. Commented Nov 27, 2013 at 4:54
  • Try static. This puts it into the static data area and avoids wasting precious stack... unlike malloc the compiler still knows where it is at compile time :) Commented Nov 27, 2013 at 5:02

2 Answers 2

8

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
Sign up to request clarification or add additional context in comments.

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.