Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > [Qt] управление памятью


Автор: kefir01 31.10.2011, 21:44
Вопрос такой... Скорее риторический...
Есть вот такой простой код

Код

    QFile file("testxml.xml");
    QByteArray ba;
    file.open(QIODevice::ReadOnly);
    ba = file.readAll();
    file.close();
    ba.clear();


Он (как можно видеть) грузит XML файл размера ~11мб и тут же удаляет загруженные данные. 
Если понаблюдать за приложением, то до запуска кода оно занимает ~13,6 мб... после запуска - ~25мб.
То есть объем возрастает на те самые ~11 мб XML файла.

При последующих нажатиях кнопки (выполняющей данный код) количество выделенной под приложение памяти не меняется в большую сторону (что хорошо и ожидаемо), однако несмотря на закрытие файла и очистку массива данных не уменьшается до положенных ~13,6 мб.

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

Мне бы хотелось временами отпускать эту память - есть ли способы? Или я что-то делаю не так?

Автор: borisbn 31.10.2011, 22:32
Цитата(kefir01 @  31.10.2011,  21:44 Найти цитируемый пост)
и тут же удаляет загруженные данные. 

Цитата(kefir01 @  31.10.2011,  21:44 Найти цитируемый пост)
несмотря на закрытие файла и очистку массива

не вижу. где ? clear ничего не делает, кроме установки внутренней переменной, отвечающей за размер, в 0.

Цитата(kefir01 @  31.10.2011,  21:44 Найти цитируемый пост)
Мне бы хотелось временами отпускать эту память - есть ли способы?

Код

void reallyClearByteArray( QByteArray & ba )
{
    QByteArray null_ba;
    std::swap( ba, null_ba );
}

Автор: bsa 31.10.2011, 22:45
а можно еще добавить вызов метода squeeze() после clear().

Автор: borisbn 31.10.2011, 22:56
А можно ещё проще
Код

ba = QByteArray();

smile

Автор: bsa 31.10.2011, 23:03
borisbn, а вот в этом не уверен - QByteArray() скорее всего выделяет память в куче (PIMPL).

Автор: borisbn 31.10.2011, 23:12
bsa, ну и что ? ba же очистится.
Вот код QByteArray::operator= из 4.7.3
Код

QByteArray &QByteArray::operator=(const QByteArray & other)
{
    other.d->ref.ref();
    if (!d->ref.deref())
        qFree(d);                 // <--- что и требовалось
    d = other.d;
    return *this;
}

Автор: kefir01 31.10.2011, 23:14
Спасибо, однако ни squeeze(), ни ba = QByteArray(); не помогли...
Может все дело в том что у меня Lion? 

Автор: ecspertiza 1.11.2011, 17:15
Мне почему то думается, что даже очистив массив память останется зарезервированной, а по необходимости ОС ее отожмет в свое распряжение.

Автор: bsa 1.11.2011, 19:55
kefir01, когда ты делаешь malloc (а new работает через malloc), то стандартная библиотека пытается выделить память в "куче". Если в ней нет подходящего свободного куска, то malloc обращается к ядру системы с целью увеличения доступной процессу памяти. Ядро просьбу удовлетворяет и ты видишь, что процесс стал жрать памяти больше. Затем ты вызываешь free (через него работает и delete), область памяти в куче становится "свободной". Но системе malloc эту память возвращать не спешит... В следующий раз выделять память он будет именно в этой области без обращения к ядру.

Автор: kefir01 1.11.2011, 23:43
bsa, спасибо. В целом я это понимаю - т.е. нет смысла отдавать память? Дже если я сначала 100мб грузанул, а потом больше 10 не буду?
Другие приложения не перекроются?

Автор: alexvs11 1.11.2011, 23:59
Цитата(kefir01 @  1.11.2011,  23:43 Найти цитируемый пост)
bsa, спасибо. В целом я это понимаю - т.е. нет смысла отдавать память? Дже если я сначала 100мб грузанул, а потом больше 10 не буду?Другие приложения не перекроются?

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

Автор: kefir01 2.11.2011, 15:25
alexvs11, я имел в виду таким образом, чтобы результат отображался в мониторе процессов...
Так-то я знаю, что надо чистить память)

Автор: bsa 2.11.2011, 17:12
Цитата(kefir01 @  2.11.2011,  16:25 Найти цитируемый пост)
alexvs11, я имел в виду таким образом, чтобы результат отображался в мониторе процессов...

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

Автор: kefir01 2.11.2011, 17:19
Ок, спасибо, друзья!

А что вы думаете по поводу qDeleteAll - насколько имеет смысл...
Насколько я понимаю есть два варианта:

1:
Код

QVector<myClass*> vec;
//...
qDeleteAll(vec);
vec.clear();


2:
Код

QVector<myClass> vec;
//...
vec.clear();


Или 2-го варианта достаточно?

Автор: borisbn 2.11.2011, 17:27
Цитата(kefir01 @  2.11.2011,  17:19 Найти цитируемый пост)
Или 2-го варианта достаточно?

конечно нет. Если в векторе лежат указатели, то под них была выделена память. Её нужно освободить.
Короче, без qDeleteAll будет leak.
Единственный вариант, когда этого делать не нужно, это когда эти указатели были запихнуты в вектор таким способом:
Код

MyClass a;
MyClass b;
QVector<myClass*> vec;
vec.push_back( &a );
vec.push_back( &b );


А ещё лучше хранить в векторе QSharedPointer или std::shared_ptr

Автор: kefir01 2.11.2011, 18:41
borisbn, во втором случае у меня объект а не указатель...

Автор: borisbn 2.11.2011, 18:56
а, да, не увидел. Думаю абсолютно всё равно, т.к. вектор всё равно хранит данные в куче.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)