Насколько большими могут быть атрибуты объекта класса?как определить предел стека / кучи? - PullRequest
4 голосов
/ 05 ноября 2010

У меня есть класс, который требует большого объема памяти.

class BigClass {
public:
    BigClass() {
        bf1[96000000-1] = 1;
    }
    double bf1[96000000];
};

Я могу инициировать класс только "новым" объектом в куче памяти.

BigClass *c = new BigClass();
assert( c->bf1[96000000-1] == 1 );
delete c;

Если я начну без "нового". Я получу ошибку сегментации во время выполнения.

BigClass c; // SIGSEGV!

Как определить предел памяти? или мне лучше всегда использовать "новый"?

Ответы [ 6 ]

3 голосов
/ 05 ноября 2010

Прежде всего, так как вы называете этот C ++, а не C, почему вы используете массивы?Вместо этого я могу предложить vector<double> или, если смежная память вызывает проблемы deque<double>, которая ослабляет ограничение на смежную память, не снимая почти постоянный поиск по времени.

Использование vector или deque также может облегчитьдругие проблемы с сегментами, которые могут помешать вашему проекту позже.Например, превышение границ в вашем массиве.Если вы преобразуете в vector или deque, вы можете использовать функцию-член .at(x) для извлечения и установки значений в вашей коллекции.Если вы попытаетесь написать вне границ, эта функция выдаст ошибку.

2 голосов
/ 05 ноября 2010

Стек имеет фиксированный размер, который зависит от параметров компилятора. См. Документацию компилятора, чтобы изменить размер стека для вашего исполняемого файла.

В любом случае, для больших объектов предпочтительнее использовать новые или лучшие: умные указатели, такие как shared_pointer (из boost или из std :: tr1 или std ::, если у вас совсем новый компилятор).

1 голос
/ 05 ноября 2010

Способ создания вашего класса, как вы обнаружили, довольно хрупок. Вместо того, чтобы всегда размещать ваши объекты в куче, вместо этого ваш класс должен выделять огромный блок памяти в куче, предпочтительно с std::vector или, возможно, с shared_ptr, если vector по какой-то причине не работает. Тогда вам не нужно беспокоиться о том, как ваши клиенты используют объект, это безопасно положить в стек или кучу.

1 голос
/ 05 ноября 2010

Ты не должен играть в эту игру никогда. Ваш код может быть вызван из другой функции или из потока с меньшим пределом размера стека, и тогда ваш код будет сорван. См. этот тесно связанный вопрос .

Если вы сомневаетесь, используйте распределение кучи (new) - либо напрямую с помощью умных указателей (например, auto_ptr), либо косвенно, используя std::vector.

1 голос
/ 05 ноября 2010

Не существует независимого от платформы способа определения предела памяти. Для «больших» объемов памяти вам гораздо безопаснее выделять в куче (то есть, используя new); Вы можете проверить успешность, сравнив результирующий указатель с NULL или обнаружив std::bad_alloc исключений.

0 голосов
/ 05 ноября 2010

В Linux в оболочке Bash вы можете проверить размер стека с помощью ulimit -s.Переменным с автоматическим хранением будет выделено место в стеке.Как уже говорили другие, есть лучшие способы решения этой проблемы:

  1. Используйте std::vector для хранения ваших данных внутри вашего BigClass.
  2. Выделите память для bf1внутри конструктора BigClass и затем освободите его в деструкторе.
  3. Если вы должны иметь большой член double[], выделите экземпляр BigClass с каким-то умный указатель ;если вам не нужен общий доступ к чему-то так простому, как std::auto_ptr позволит вам безопасно построить / уничтожить ваш объект:

    std::auto_ptr<BigClass>(new BigClass) myBigClass;
    myBigClass->bf1; // your array
    
...