Форум программистов, компьютерный форум CyberForum.ru

Освобождение памяти, занятой вектором - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 29, средняя оценка - 5.00
Union
 Аватар для Union
17 / 17 / 2
Регистрация: 16.08.2010
Сообщений: 252
07.09.2011, 14:30     Освобождение памяти, занятой вектором #1
У меня задача требует чтобы у вектора было в резерве не более 100 элементов. При постоянном росте вектора понятно как это обеспечить, а вот как быть при уменьшении количества элементов? Я не в курсе последних стандартов, подскажите есть ли сейчас способы гарантированного освобождения памяти, занятой вектором, и вообще какие способы существуют?
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.09.2011, 14:30     Освобождение памяти, занятой вектором
Посмотрите здесь:

C++ Освобождение памяти
C++ Освобождение памяти
резервирование памяти/освобождение памяти для трехмерного массива C++
Освобождение памяти C++
C++ освобождение памяти
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
-=ЮрА=-
Заблокирован
Автор FAQ
08.09.2011, 11:34     Освобождение памяти, занятой вектором #41
Цитата Сообщение от alex_x_x Посмотреть сообщение
конструктор анонимного объекта
- поэтому и ввёл int i в конструктор, т.е в реальной программе - это наша начальная инициализация, что сделать массив CFileDialog с тайтлами появляющихся окон Окно № i ???Я уже устал от разборов, сейчас накидаю проект...
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
fasked
Эксперт C++
 Аватар для fasked
4925 / 2505 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
08.09.2011, 11:36     Освобождение памяти, занятой вектором #42
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
поэтому и ввёл int i в конструктор, т.е в реальной программе - это наша начальная инициализация, что сделать массив CFileDialog с тайтлами появляющихся окон Окно № i ???Я уже устал от разборов, сейчас накидаю проект...
Да не нужны никому эти CFileDialog, мы даже посмотреть не сможем на результат, окромя Ваших скринов... Просто создайте простенький класс, в котором динамически выделяется память в конструкторе и освобождается в деструкторе.
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
08.09.2011, 11:44     Освобождение памяти, занятой вектором #43
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
неа я из каменного века
Именно из него. Перед присваиванием нужно разрушить текущее состояние объекта, но никакого состояния нет, т.к там мусор. В данном случае код работает исключительно по ошибке, для не POD типов этот код не работает. Т.е. можно утверждать, что он НЕ рабочий. Причём, даже вызов memset после перераспределения памяти не сделает этот код рабочим. В общем, не надо так никогда делать.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
08.09.2011, 11:49     Освобождение памяти, занятой вектором #44
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Сначало вызвать деструкторы для нужных объектов, потом обрезать память, в моём примере именно так и сделано...
Юра, а вы залезьте в недры заголовочников вашего компилятора и посмотрите, как устроен std::allocator (и классы, от которых он наследует). Там так и сделано. Одна функция (метод, если вам угодно) - это deallocate, другая - destroy.

Вся STL работает по принципу "конструктор-деструктор", так, как Страуструп прописал. Все человеческие библиотеки так работают. Вы ведь не с нами спорите, вы ведь со стандартом C++ и с нормами ООП спорите. Не занимайтесь ерундой, почитайте, лучше, умных книжек. Ну или, хотя бы, вот это. Про назначение конструктора в особенности.
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
08.09.2011, 11:52     Освобождение памяти, занятой вектором #45
Цитата Сообщение от Union Посмотреть сообщение
задача требует чтобы у вектора было в резерве не более 100 элементов.
Стоит задуматься об использовании иных контейнеров, т.к. при большом количестве элементов распределение памяти становится неэффективным. Стандартная реализация обеспечивает в среднем два копирования при любом размере vector'a. Если в резерве держать не более 100 элементов, то копирований будет намного больше(чем больше длина вектора, тем больше лишних копирований).
Особенно это критично будет при неэффективном копировании вектора больших объектов.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
08.09.2011, 11:57     Освобождение памяти, занятой вектором #46
-=ЮрА=-, не верите в динамическое выделение памяти, вот другой пример: таблица виртуальных функций. Конструкторы (и только конструкторы) её настраивают, никакими void Init() вы не отделаетесь.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
#include <stdlib.h> // для malloc
 
using namespace std;
 
class CDummy
{
public:
    CDummy(){};
 
    virtual void out() = 0;
};
 
class CStrDummy : public CDummy
{
public:
    CStrDummy() : CDummy(){};
 
    virtual void out(){
        cout << "String\n";
    }
};
 
class CIntDummy : public CDummy
{
public:
    CIntDummy() : CDummy(){};
 
    virtual void out(){
        cout << 256;
    }
};
 
int main()
{
    // так не работает (никто не настроил таблицу виртуальных функций)
    /*
    CStrDummy * strPtr = (CStrDummy*)malloc( sizeof(CStrDummy) );
    CIntDummy * intPtr = (CIntDummy*)malloc( sizeof(CIntDummy) );
    */
 
    // так работает:
    CStrDummy * strPtr = new CStrDummy();
    CIntDummy * intPtr = new CIntDummy();
 
    CDummy * dum = strPtr;
    dum->out();
    dum = intPtr;
    dum->out();
 
    // в случае с malloc до сюда просто не дойдёт
    delete strPtr;
    delete intPtr;
 
    return 0;
}
Union
 Аватар для Union
17 / 17 / 2
Регистрация: 16.08.2010
Сообщений: 252
08.09.2011, 21:18  [ТС]     Освобождение памяти, занятой вектором #47
Deviaphan, нет, другой контейнер не подойдет, т.к. есть одна тонкость, нужна мгновенная сортировка по запросу.

Господа, подведите итоги пжалуста , ушли в личные беседы...
Mr.X
Эксперт С++
 Аватар для Mr.X
2807 / 1583 / 248
Регистрация: 03.05.2010
Сообщений: 3,696
08.09.2011, 21:50     Освобождение памяти, занятой вектором #48
Цитата Сообщение от Union Посмотреть сообщение
нужна мгновенная сортировка по запросу.
Может тогда std::multiset использовать? Он всегда отсортирован,
и лишней памяти не запрашивает.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
08.09.2011, 23:06     Освобождение памяти, занятой вектором #49
Union, вот мои итоги. Насколько могу судить, вектор (по крайней мере у меня) не отдаёт память после resize() в меньшую сторону. Тупо деструкторы вызывает и всё.
villu
202 / 202 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
08.09.2011, 23:30     Освобождение памяти, занятой вектором #50
вектор (по крайней мере у меня) не отдаёт память после resize()
и не должен. Иначе пришлось бы заниматься ненужным копированием.
Освобождение памяти, занятой вектором тут еще это сказал.
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
09.09.2011, 06:41     Освобождение памяти, занятой вектором #51
Цитата Сообщение от Union Посмотреть сообщение
нужна мгновенная сортировка по запросу
Мгновенной сортировки не бывает. Это фантастика.
Есть std::set - это не фантастика.

Тут ещё один момент не учли. Создавая копию вектора меньшего размера создаётся его копия. Т.е. потребление памяти временно удваивается. Использование аллокатора эту проблему не решает, т.к. он выделяет память, а не перераспределяет имеющуюся в векторе (или нужно очень сильно над реализацией попотеть, но по моему для std::vector нельзя написать аллокатор через realloc, чтобы не создавать копию вектора, ведь для этого придётся переписывать логику работы вектора).

Итого: Пиши собственный контейнер используя malloc/realloc/free и размещающий new. Или я недостаточно хорошо знаю std::vector.)
LosAngeles
Заблокирован
09.09.2011, 06:50     Освобождение памяти, занятой вектором #52
раздули на шесть страниц какую то фигню, чем вариант со своп не устраивает ТС, вот даже код привёл Мистер Хэ
Цитата Сообщение от Mr.X Посмотреть сообщение
void do_minimize_capacity(T_container& v)
{
T_container(v).swap(v);
}
Добавлено через 44 секунды
и никаких копий не создаётся
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
09.09.2011, 06:54     Освобождение памяти, занятой вектором #53
Цитата Сообщение от LosAngeles Посмотреть сообщение
и никаких копий не создаётся
По твоему безымянный объект T_container(v) не копия?
LosAngeles
Заблокирован
09.09.2011, 07:14     Освобождение памяти, занятой вектором #54
да создаётся, я просто не посмотрел что копировал. Но адаптировать данный пример под требования автора

Цитата Сообщение от Union Посмотреть сообщение
подскажите есть ли сейчас способы гарантированного освобождения памяти, занятой вектором
переделать просто:
C++
1
2
3
4
5
template<class T_container>
void clear(T_container& v)
{
    T_container().swap(v);
}
никаких копий не создаётся
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
09.09.2011, 07:27     Освобождение памяти, занятой вектором #55
Цитата Сообщение от LosAngeles Посмотреть сообщение
переделать просто:
Это удаляет ВСЕ объекты из контэйнера, а требуется удалить только "лишнюю" зарезервированную память, а не очистить. По крайней мере фразу "уменьшение количества элементов" я не приравниваю к слову "очистить".
Кстати, используя вектор в куче, вместо стэка, проблема с гарантированным освобождением памяти решается пересозданием объекта.)
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
09.09.2011, 11:54     Освобождение памяти, занятой вектором #56
На счёт другого контейнера: если std::list устроит вас по скорости обхода и количеству избыточной информации на узел (вроде, два указателя и всё, но я могу ошибаться) - то его можно обрезать под нужную длину без пересоздания кучи элементов. и память освобождается (gcc 4.9 mingw)
Union
 Аватар для Union
17 / 17 / 2
Регистрация: 16.08.2010
Сообщений: 252
09.09.2011, 19:43  [ТС]     Освобождение памяти, занятой вектором #57
Про своп я уже написал, когда я изучал эту тему, не нашел нигде инфы по поводу гарантии со стороны стандарта что новый вектор будет меньше старого. А сейчас вот не знаю и спрашиваю...

Тогда ещё такой вопрос, что делает malloc_trim(0) ?
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
09.09.2011, 20:01     Освобождение памяти, занятой вектором #58
Union, в манах сказано так:

malloc_trim() explicitly requests that any unused memory space be returned to the OS. Note that this happens automatically when free() is called with a sufficiently large chunk; see the M_TRIM_THRESHOLD and M_TOP_PAD parameters, above. pad specifies the number of bytes to be retained for use in future allocation requests; when called by free(), this is the value of M_TOP_PAD.
Добавлено через 3 минуты
malloc_trim() явным образом возвращает любую неиспользованную память системе. Это проиходит автоматически, когда вызывается free() для достаточно большого сегмента кучи. См. параметры M_TRIM_THRESHOLD и M_TOP_PAD выше (здесь ниже). pad определяет количество байт, которые необходимо оставить для запросов на выделение памяти в будущем. Когда вызывается из free(), это значение равно M_TOP_PAD.

Добавлено через 5 минут
M_TRIM_THRESHOLD
Unused memory is returned to the OS when the size available to be returned exceeds the given value.

Note that not all unused memory is able to be returned to the OS; in particular, it is not possible to return an unused block when an in-use block lies between it and the ``top'' of the data segment. However, the free block may be used to satisfy future allocation requests.

Smaller values for this parameter cause sbrk() to be called more frequently with a negative argument, reducing memory usage, but with increased overhead of extra syscalls. A value of -1 disables trimming. Default: 128*1024.
M_TRIM_THRESHOLD
Неиспользованная память возвращается системе, когда размер памяти, доступной для возврата, превышает данное значение.

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

Меньшие значения для этого параметра приводят к тому, что sbrk() вызывается чаще с отрицательным аргументом, уменьшая использование памяти, но увеличивая накладные расходы на дополнительные системные вызовы. Значение -1 запрещает (отсечение? возврат памяти ОС?). Значение по-умолчанию: 128*1024.

Добавлено через 4 минуты
M_TOP_PAD
When sbrk() is called with a positive argument to allocate additional address space, the given value specifies an additional amount to be allocated, beyond what is necessary to satisfy the request. This value also defines an amount of address space which is not released to the OS when sbrk() is called with a negative argument. Again, the intent is to minimize the number of syscalls, without needlessly using large usage of memory. Default: 0 (allocation requests are internally rounded up to the page size, and the extra allocated size is already sufficient to reduce the syscall overhead).
M_TOP_PAD
Когда для выделения дополнительного адресного пространства вызывается sbrk() с положительным аргументом, данное значение определят количество памяти, выделяемой сверх необходимого. Это значение также определяет количество адресного пространства, которое не отдаётся системе когда вызывается sbrk() с отрицательным аргументом. Смысл этого - в уменьшении количества системных вызовов без увеличения нецелесообразного расхода памяти. Значение по-умолчанию: 0 (запросы на выделение памяти округляются в большую сторону до размера страницы, и памяти, выделенной дополнительно, достаточно для уменьшения расходов на системные вызовы.

Добавлено через 1 минуту
Короче, вот эта страница в сети.
Mr.X
Эксперт С++
 Аватар для Mr.X
2807 / 1583 / 248
Регистрация: 03.05.2010
Сообщений: 3,696
09.09.2011, 20:27     Освобождение памяти, занятой вектором #59
Цитата Сообщение от Union Посмотреть сообщение
Про своп я уже написал, когда я изучал эту тему, не нашел нигде инфы по поводу гарантии со стороны стандарта что новый вектор будет меньше старого. А сейчас вот не знаю и спрашиваю...
В стандарте написано только:
«The constructor template <class InputIterator> vector(class InputIterator first, class InputIterator last) makes only N calls to the copy constructor of T (where N is the distance between first and last) and no reallocations if iterators first and last are of forward, bidirectional, or random access categories. It makes order N calls to the copy constructor of T and order logN reallocations if they are just input iterators.»
С другой стороны, этот «трюк» со свопом приводят в своих книгах такие столпы C++ как Степанов (создатель STL), Остерн (один из разработчиков SGI STL), а также всем ведомый Александреску.
А чем вас std::multiset не устраивает?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.11.2013, 14:29     Освобождение памяти, занятой вектором
Еще ссылки по теме:

с++ Освобождение памяти C++
C++ Освобождение памяти
C++ Освобождение памяти

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
SatanaXIII
Супер-модератор
Эксперт С++
 Аватар для SatanaXIII
5549 / 2563 / 233
Регистрация: 01.11.2011
Сообщений: 6,337
Завершенные тесты: 1
12.11.2013, 14:29     Освобождение памяти, занятой вектором #60
Нда. Короче поговорили про память, но не поговорили про вектор.
Почему не срабатывает трюк непосредственно с самим вектором?
C++
1
v.swap(v);
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream.h>
#include <vector.h>
 
int main()
{
vector<int> v;
  v.reserve(100000);
 v.push_back(1);
 v.push_back(2);
 v.push_back(3);
cout << "size=" << v.size() << endl;
cout << "capacity=" << v.capacity() << endl;
 
v.erase(v.begin(), v.end()); ////
v.clear();                     //
v.resize(0);                   //
v.reserve(1);                ////
 
v.swap(v);
 
cout << "size=" << v.size() << endl;
cout << "capacity=" << v.capacity() << endl;
 
 
cin.ignore();
return 0;
}
Код
size=3
capacity=100000
size=0
capacity=100000
Yandex
Объявления
12.11.2013, 14:29     Освобождение памяти, занятой вектором
Ответ Создать тему
Опции темы

Текущее время: 11:24. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru