Накормите QList другим

привет, я пытаюсь отправить QList в качестве параметра другому классу, но по какой-то причине я получил нарушение доступа для чтения...

CompareTimeChannel.h

 class CompareTimeChannel : public IDataChannel
   public:

      // @brief The method used to receive the list
      void setData(const QList< QSharedPointer<core::ITrackSection> > & sections);

      // @brief The list
      QList< QSharedPointer<core::ITrackSection> > _sections;

 };

CompareTimeChannel.cpp

 // @brief Empty constructor
 CompareTimeChannel::CompareTimeChannel()
 {
 }

 void CompareTimeChannel::setData(const QList< QSharedPointer<core::ITrackSection> > & sections)
 {
     //_sections = *new QList< QSharedPointer<core::ITrackSection> > ();
     _sections.clear();
     _sections.append(sections);
 }

Запуск этого кода вызовет Exception at 0x31cc78d, code: 0xc0000005: read access violation at: 0x4, flags=0x0 на _sections.clear();

Я пытался инициализировать список раньше (закомментированная строка _sections = *new QList<...>), но исключение выдается то же самое.

Ответ был бы очень признателен...

ИЗМЕНИТЬ

Хорошо, это исправлено!

Во-первых, как сказал @AndreasT, мне пришлось инициализировать конструктор QList по умолчанию.

Затем, согласно ответу @ 10WaRRioR01, проблема возникает из-за CompareTimeChannel, который не был инициализирован при первом вызове метода. Исправлено с помощью:

        CompareTimeChannel* chan = static_cast<CompareTimeChannel*>(channel);
        Q_ASSERT(chan);
        if (chan) {
            chan->setData(sections);
        }
        else {
            qDebug() << "Dynamic cast failure";
        }

Всем спасибо, ребята!


person user2140122    schedule 06.03.2013    source источник


Ответы (3)


//_sections = *new QList< QSharedPointer<core::ITrackSection> > ();

Вы никогда не должны делать что-то подобное. Это создает новый экземпляр QList в куче, и он никогда не будет удален, так что у вас есть утечка памяти
Вы должны были сделать

_sections = QList< QSharedPointer<core::ITrackSection> > ();

вместо этого, и это было бы законно. Но самый простой способ - использовать такое назначение копирования

_sections = sections

Проблема, с которой вы столкнулись, скорее всего, связана с данными, которые у вас есть в _sections. Возможно, вы вызываете свои методы для нулевого объекта CompareTimeChannel.

person spiritwolfform    schedule 06.03.2013
comment
Проблема, с которой вы столкнулись, скорее всего, связана с данными, которые у вас есть в _sections. -› вы имеете в виду, что проблема должна исходить от core::ITrackSection ? - person user2140122; 06.03.2013
comment
Да, я так думаю. Остальной код выглядит нормально. Возможно, вам не хватает виртуального деструктора или чего-то еще. - person spiritwolfform; 06.03.2013
comment
в этом случае, может ли эта проблема возникнуть, если списки _sections и section пусты? - person user2140122; 06.03.2013
comment
нет. Но если вы даже не можете получить доступ к размеру своего списка, вам следует проверить, вызываете ли вы setData() для нулевого объекта. - person spiritwolfform; 06.03.2013
comment
хорошо... итак, два вопроса: 1) могу ли я проверить, является ли объект, переданный setData(), null? 2) я не могу получить доступ к размеру члена класса _sections, объявленному в CompareTimeChannel.h, это относится к параметру setData()? - person user2140122; 06.03.2013
comment
я имею в виду, что сам объект CompareTimeChannel может быть нулевым. Поскольку вы делаете это: dynamic_cast<CompareTimeChannel*>(channel)->setData(sections);, если dynamic_cast возвращает значение null, скорее всего, мы получим ту же ошибку, что и вы. Проверка возвращаемого значения dynamic_cast считается хорошей практикой. - person spiritwolfform; 06.03.2013

Вы должны инициализировать разделы в конструкторе. Закомментированная строка просто ужасно неверна.

new создает список в куче, затем вы разыменовываете его с помощью *new, и присваивание неявно вызывает конструктор копирования нового списка в куче и копирует его в экземпляр. Тем не менее, вещь в куче все еще существует, поэтому вы только что создали утечку памяти.

// @brief Empty constructor
 CompareTimeChannel::CompareTimeChannel()
:_sections()   // initialization default constructor.
 {
 }

Редактировать комментарий:

Метод QList.clear() вызывает деструкторы каждого элемента списка. По крайней мере, один из ваших общих указателей неправильно инициализирован. Если вам нужна дополнительная информация, вставьте код, который помещает материал в _sections.

Редактировать относительно исключения: Как я уже сказал, проблема, скорее всего, в том, что общие указатели не установлены на что-либо интересное. Когда SP уничтожается, он вызывает деструктор своего содержимого, которое должно существовать, в противном случае выдается нарушение прав на чтение, что объясняет симптомы.

person AndreasT    schedule 06.03.2013
comment
Закомментированная строка просто ужасно неверна. Ахах :) Но я получаю ту же ошибку, но теперь на _sections.append(sections); => Исключение по адресу 0x300c78d, код: 0xc0000005: нарушение доступа для чтения по адресу: 0x4, flags=0x0 - person user2140122; 06.03.2013
comment
Хорошо... но я не хочу уничтожать все объекты внутри списка, просто удаляю элементы из списка, согласно документации QList. Код, который загружает разделы (названные в этом классе _sec): void GraphModel::addSection(const QSharedPointer‹core::ITrackSection› & section) { _mutex.lock(); _selectionUpdated = Истина; _sec ‹‹ раздел; _condition.wakeOne(); _mutex.unlock(); } - person user2140122; 06.03.2013
comment
Я понимаю, но не понимаю, почему SharedPointers уничтожаются... или QList::clear не тот метод, который мне нужен... Теперь позвольте мне заменить метод setData на: void CompareTimeChannel::setData(const QList< QSharedPointer<core::ITrackSection> > & sections) { qDebug() << "Size:" << _sections.size(); } Я получаю ту же ошибку, просто прочитав... - person user2140122; 06.03.2013

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

Первое, что я попытался бы сделать:

make clean
qmake
make

Это решает такую ​​проблему довольно часто. если я не помогу, вам придется найти другие проблемы в вашем коде.

person Marek R    schedule 06.03.2013
comment
Я постараюсь. Я не знаю, актуально ли это, но метод setData() вызывается так: dynamic_cast<CompareTimeChannel*>(channel)->setData(sections); - person user2140122; 06.03.2013