2013-11-27 3 views
3

Так у меня есть этот сложный класс, и я хочу, чтобы иметь 2d массив комплексных чисел это часть кода не весь кодстека в программе C++

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]; 
} 

поэтому линия комплекс G [ ВЫСОТА ШИРИНА]; это линия, которая вызывает проблему, любая идея, почему?

+3

Предполагая, что 8-байтовый двойной, это 1 МБ стекового хранилища для 'G', что обычно является общим пределом. – chris

+0

Потому что вы переполняете стек 65536 объектов 'Complex'. Это действительно не ... сложный ... предмет для понимания. –

+0

Лучше не выделять большие массивы в стеке - используйте 'malloc' - и, возможно, создайте функцию доступа как часть класса, чтобы упростить индексирование. – Floris

ответ

7

Визуальные по умолчанию студии к размеру стека 1Мб, он выглядит следующим образом:

Complex G[HEIGHT][WIDTH]; 

будет только около 1 Мб, вы можете изменить это с помощью /F и говорится в документе (внимание мое):

Без этой опции размер стека по умолчанию составляет 1 МБ. Аргумент number может быть в десятичной или C-языковой нотации. Аргумент может варьироваться от 1 до максимального размера стека, принятого компоновщиком. Компоновщик округляет указанное значение до ближайших 4 байтов. Пространство между/F и number является необязательным.

Наиболее очевидной альтернативой было бы использовать динамическое выделение памяти с помощью новой или std::vector.

Visual Studio насколько я знаю, на самом деле имеет one of the smaller default размеры стеков:

platform default size  
===================================== 
SunOS/Solaris 8192K bytes 
Linux   8192K bytes 
Windows  1024K bytes 
cygwin   2048K bytes 
Mac OS X  8192K bytes 
1

Любая идея, почему?

Некоторые компиляторы по умолчанию имеют размер стека до 1 МБ. Вы выделяете 65536 Complex объектов, которые занимают 2 * sizeof(double) памяти каждый. Предполагая, что double будет иметь 8 байтов (эта информация определена реализацией), вы фактически пытаетесь выделить 16 * 65536 байт (без учета возможных прокруток), которые составляют 1048576 байт, что вызывает переполнение.

Альтернативой с использованием динамического распределения с оболочкой, которая имитирует двумерная индексацию массива, вдоль линий этого:

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]; 
    } 
}; 

Затем программа просто становится:

int main(int, char*[]) { 
    G<256, 256> g; 
    g(0, 0) = ...; 
} 

Конечно, вы можете обобщить свою обертку G для типового типа с шаблонами, но это выходит за рамки этого ответа.


На стороне записки, вы деструктор:

~Complex() { r=0.0; i=0.0; } 

бесполезно. Не перезапускайте память, которая будет уничтожена, когда она покинет область действия.

Смежные вопросы