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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Что за WTF с распределением памяти в QVector?  (Прочитано 630 раз)
vertus
Новичок

Offline Offline

Сообщений: 40


« : Февраль 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
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3231



« Ответ #1 : Февраль 05, 2012, 19:44 »

А ты попробуй в цикле выводить еще и адрес начала вектора:
qDebug() << &vector[ 0 ] << &(vector);
Записан

Каждое препятствие – это возможность.
vertus
Новичок

Offline Offline

Сообщений: 40


« Ответ #2 : Февраль 05, 2012, 19:47 »

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

Записан
zenden
Крякер
****
Offline Offline

Сообщений: 322

Qt Addicted


« Ответ #3 : Февраль 05, 2012, 19:54 »

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

Offline Offline

Сообщений: 40


« Ответ #4 : Февраль 05, 2012, 19:56 »

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

При чем здесь это? В одном месте программы адресс на первые два элемента один, а вдругом месте другой! При этом никаких перестановок не производилось в векторе!
Записан
BRE
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3231



« Ответ #5 : Февраль 05, 2012, 20:08 »

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

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

Каждое препятствие – это возможность.
vertus
Новичок

Offline Offline

Сообщений: 40


« Ответ #6 : Февраль 05, 2012, 20:16 »

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

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


Все равно не понятно. Даже если предположить, что изначальная емкость была меньше десяти элементов, он должен был дополнительно выделить память, а не перераспределить её. Разве не так?
Записан
BRE
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3231



« Ответ #7 : Февраль 05, 2012, 20:21 »

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

Каждое препятствие – это возможность.
vertus
Новичок

Offline Offline

Сообщений: 40


« Ответ #8 : Февраль 05, 2012, 20:24 »

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


Да, я стормозил. С таким раскладом к элементам вектора вообще нельзя обращаться по адресу.
Записан
BRE
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3231



« Ответ #9 : Февраль 05, 2012, 20:26 »

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

Каждое препятствие – это возможность.
mutineer
Гипер активный житель
*****
Offline Offline

Сообщений: 869



« Ответ #10 : Февраль 05, 2012, 23:33 »

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

Конечно нельзя и в документации по векторам (в stl точно, в Qt не помню) это написано
Записан

Запомните - сначала учить плюсы, и только потом Qt!!
-------------------------------------------------------
Переломать всем ноги и пусть никто не уйдет обиженным
pastor
Administrator
Джедай : наставник для всех
*****
Online Online

Сообщений: 2871



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
Крякер
****
Offline Offline

Сообщений: 379



« Ответ #12 : Февраль 06, 2012, 02:13 »

http://developer.qt.nokia.com/doc/qt-4.8/containers.html
Записан
vertus
Новичок

Offline Offline

Сообщений: 40


« Ответ #13 : Февраль 06, 2012, 09:48 »

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

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

Сообщений: 869



« Ответ #14 : Февраль 06, 2012, 11:11 »

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

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

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

Запомните - сначала учить плюсы, и только потом Qt!!
-------------------------------------------------------
Переломать всем ноги и пусть никто не уйдет обиженным
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  

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