Russian Qt Forum
Май 05, 2024, 06:58 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Что за WTF с распределением памяти в QVector?  (Прочитано 12317 раз)
vertus
Гость
« : Февраль 05, 2012, 19:38 »

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

Вот простой пример демонстрирующий инцидент:

Код:
#include <QtCore/QCoreApplication>
#include <QVector>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QVector<int> vector;

    qDebug() << "Begin in scope\n";

    for (int i = 0; i < 10; i++)
    {
        vector.push_back(i);
        qDebug() << &(vector[i]);
    }

    qDebug() << "\nEnd in scope\n";

    for (int i = 0; i < 10; i++)
    {
        qDebug() << &(vector[i]);
    }

    return a.exec();
}

Теперь смотрим на вывод. Адресс на первые два элемента в перовом цикле не совпадает с адресом на первые 2 элемента во втором, а остальные адреса совпадают!

WTF???



Записан
BRE
Гость
« Ответ #1 : Февраль 05, 2012, 19:44 »

А ты попробуй в цикле выводить еще и адрес начала вектора:
qDebug() << &vector[ 0 ] << &(vector);
Записан
vertus
Гость
« Ответ #2 : Февраль 05, 2012, 19:47 »

Одинаковый!!!

Записан
zenden
Гость
« Ответ #3 : Февраль 05, 2012, 19:54 »

Ну и в чем собственно проблема?
QVector заранее выделяет больше памяти, чем требуется, чтобы избежать накладных расходов при добавлении элементов.
Записан
vertus
Гость
« Ответ #4 : Февраль 05, 2012, 19:56 »

Ну и в чем собственно проблема?
QVector заранее выделяет больше памяти, чем требуется, чтобы избежать накладных расходов при добавлении элементов.

При чем здесь это? В одном месте программы адресс на первые два элемента один, а вдругом месте другой! При этом никаких перестановок не производилось в векторе!
Записан
BRE
Гость
« Ответ #5 : Февраль 05, 2012, 20:08 »

Ну и в чем собственно проблема?
QVector заранее выделяет больше памяти, чем требуется, чтобы избежать накладных расходов при добавлении элементов.
Скорее наоборот, вектор перераспределяет память заново с копированием элементов.

Вот так, думаю будет виднее:
Код
C++ (Qt)
qDebug() << &vector[ 0 ] << &(vector[i]);
« Последнее редактирование: Февраль 05, 2012, 20:48 от BRE » Записан
vertus
Гость
« Ответ #6 : Февраль 05, 2012, 20:16 »

Ну и в чем собственно проблема?
QVector заранее выделяет больше памяти, чем требуется, чтобы избежать накладных расходов при добавлении элементов.
Скорее наоборот, вектор перераспределяет память заново с копированием элементов.

Вот так, думаю будет виднее:
qDebug() << &vector[ 0 ] << &(vector);


Все равно не понятно. Даже если предположить, что изначальная емкость была меньше десяти элементов, он должен был дополнительно выделить память, а не перераспределить её. Разве не так?
Записан
BRE
Гость
« Ответ #7 : Февраль 05, 2012, 20:21 »

он должен был дополнительно выделить память, а не перераспределить её. Разве не так?
А ты знаешь средства в C++ для дополнительного выделения памяти?
Записан
vertus
Гость
« Ответ #8 : Февраль 05, 2012, 20:24 »

он должен был дополнительно выделить память, а не перераспределить её. Разве не так?
А ты знаешь средства в C++ для дополнительного выделения памяти?


Да, я стормозил. С таким раскладом к элементам вектора вообще нельзя обращаться по адресу.
Записан
BRE
Гость
« Ответ #9 : Февраль 05, 2012, 20:26 »

С таким раскладом к элементам вектора вообще нельзя обращаться по адресу.
Если его изменять, то конечно.
Записан
mutineer
Гость
« Ответ #10 : Февраль 05, 2012, 23:33 »

Да, я стормозил. С таким раскладом к элементам вектора вообще нельзя обращаться по адресу.

Конечно нельзя и в документации по векторам (в stl точно, в Qt не помню) это написано
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #11 : Февраль 06, 2012, 00:02 »

Цитировать
Unlike plain C++ arrays, QVectors can be resized at any time by calling resize(). If the new size is larger than the old size, QVector might need to reallocate the whole vector. QVector tries to reduce the number of reallocations by preallocating up to twice as much memory as the actual data needs.

QVector::push_back is equivalent to append.
QVector::append is the same as calling resize(size() + 1) and assigning value to the new last element in the vector.

Это все из документации по QVector
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
thechicho
Гость
« Ответ #12 : Февраль 06, 2012, 02:13 »

http://developer.qt.nokia.com/doc/qt-4.8/containers.html
Записан
vertus
Гость
« Ответ #13 : Февраль 06, 2012, 09:48 »

Всем спасибо, я все понял.

А с QList таких приколов нет? По идее там даже в случае перестановки переназначается указетель на следующий элемент, а сама память не трогается.
« Последнее редактирование: Февраль 06, 2012, 09:50 от vertus » Записан
mutineer
Гость
« Ответ #14 : Февраль 06, 2012, 11:11 »

Всем спасибо, я все понял.

А с QList таких приколов нет? По идее там даже в случае перестановки переназначается указетель на следующий элемент, а сама память не трогается.

QList загадочная вещь и ведет себя в зависимости от размера хранимого объекта. QLinkedList ведет себя так, как тебе нужно. Но все равно хранить прямые указатели на элементы контейнера потенциально опасно
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.076 секунд. Запросов: 23.