Плохо ли хранить большие векторы в стеке?

Я работал над кучей программ обработки изображений... ничего особенного, в основном экспериментировал быстро и грязно. Данные изображения хранятся в векторах, которые объявлены в стеке (я стараюсь избегать использования указателей, когда мне не нужно передавать данные). Я заметил, что некоторые из моих функций ведут себя очень странно, несмотря на бесчисленное количество отладки и пошагового выполнения. Иногда отладчик, среди прочего, выдавал мне ошибку, что он не может оценить определенную переменную. Вещи, как правило, просто не имеют смысла, и прошлый опыт подсказывает мне, что когда это происходит, это означает, что происходит какое-то переполнение или повреждение памяти. Первое, что пришло на ум, это то, что это, вероятно, связано с тем, что я храню много данных изображения в векторах.

Однако у меня сложилось впечатление, что векторы хранят свои фактические данные в куче, и поэтому я подумал, что не повредит иметь несколько таких больших векторов в стеке. Я ошибаюсь, думая об этом? Должен ли я выделять свои векторы и хранить их в куче, а не в стеке?

Спасибо,


person 9a3eedi    schedule 07.06.2012    source источник
comment
Содержимое вектора выделяется динамически. Сам векторный объект обычно крошечный (12-24 байта).   -  person Blastfurnace    schedule 07.06.2012
comment
Я обнаружил проблему, с которой столкнулся. Я выходил за пределы вектора, который, как я предполагал, будет в 3 раза больше, чем он есть на самом деле. Спасибо всем за разъяснение того, как работает распределение векторов. Это заставило меня посмотреть в правильном направлении!   -  person 9a3eedi    schedule 07.06.2012


Ответы (3)


[...] векторы хранят свои фактические данные в куче

vector, как и все другие контейнеры, использует объект-распределитель для управления памятью. Как правило, если вы ничего не указываете в качестве второго параметра шаблона, используется распределитель по умолчанию -- std::allocator из <memory> --. Ответственность за резервирование памяти лежит на распределителе. Это можно сделать бесплатно либо в свободном хранилище, либо в стеке.

Большинство реализаций обычно используют идиому pimpl и сохраняют указатель в объекте vector, который указывает на фактическую память в свободном хранилище.

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

Вы можете проверить, правильно ли вы используете свои vector. Посмотрите стандарт, какие гарантии вы получаете с каждой функцией-членом, какие условия должны быть выполнены для содержащихся типов и когда ваши итераторы становятся недействительными. Это должно быть хорошим началом.

person dirkgently    schedule 07.06.2012
comment
Понятно.. Полагаю, это не та проблема, с которой я столкнулся. Я собираюсь пойти дальше и проверить свой код должным образом... Я делаю некоторые хаки для повышения производительности, может быть, мне стоит посмотреть туда. Существуют ли какие-либо инструменты, которые могут проверить повреждение памяти? - person 9a3eedi; 07.06.2012
comment
Зависит от вашей платформы. Большинство платформ имеют тот или иной инструмент. Найдите на этом сайте такой инструмент (Valgrind для Linux, Purify для Windows и т. д.), который лучше всего соответствует вашим потребностям. - person dirkgently; 07.06.2012
comment
Спасибо, я проверю valgrind - person 9a3eedi; 07.06.2012

std::vector не хранит свою память внутри себя. Он выделяет память из кучи (или откуда ее получает ваш распределитель). Поэтому не имеет значения, находится ли vector сам в стеке.

person Nicol Bolas    schedule 07.06.2012

Я бы сказал, что 99,9% векторных реализаций хранят все свои данные в куче. Может быть, кто-то сделал реализацию стека, но вы, вероятно, не имеете с этим дело. Если происходят случайные, прерывистые сбои, более вероятным случаем является отсутствие проверки с помощью арифметики указателей. В любом случае, мы не сможем узнать, если вы не опубликуете код.

person Robert Mason    schedule 07.06.2012
comment
Может быть, кто-то сделал реализацию стека, но вы, вероятно, не имеете с этим дело. Это было бы невозможно. vector не выделяет память; распределитель vector делает это. А std::allocator по умолчанию получает память из кучи. - person Nicol Bolas; 07.06.2012
comment
@Nicol: Но не все соответствуют стандарту. Может быть, кто-то решил сделать что-то сумасшедшее и заставить распределитель по умолчанию запускать специализацию шаблона, которая делает сумасшедшие вещи, такие как ручное манипулирование esp/rsp, копирование вещей, а затем поиск в стеке указателей на местоположения в стеке и изменение этих указателей. Случались странные вещи. - person Robert Mason; 07.06.2012
comment
@RobertMason: Если ваш аргумент таков, но все может случиться! тогда какой смысл даже догадываться о простейших вещах? Что, если int i на самом деле float i, не все согласятся! - person GManNickG; 07.06.2012
comment
Я бы опубликовал свой код, но дело в том, что я не уверен, что публиковать, лол ... если это имеет смысл. Я храню 2 векторных объекта (изображения) в другом классе, а затем выделяю этот класс в стеке, когда хочу его использовать. Единственное, что в этих классах занимает много места, это векторы. - person 9a3eedi; 07.06.2012