Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: код ошибки -1073741819
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Общие вопросы
demaker
Никак не могу отловить ошибку.
Вроде все что создавал на куче удаляю за собой.

И все равно выдает.

завершился с кодом -1073741819

Использую библиотеку QWT

когда в дебаге отлавливаю то программа вылетает здесь:
template <typename T>
QwtPlotSeriesItem<T>::~QwtPlotSeriesItem()
{
    delete d_series;
}


а начинается на этом участке:
void Widget::sl_deletePlot(QTreeWidgetItem*item,int column)
{
    qDebug()<<"sl_deletePlot";
    qDebug()<<"plot = "<<((TreeWidgetItem*)item)->p;

    ((TreeWidgetItem*)item)->p->deleteLater();    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    listPlot.removeOne(((TreeWidgetItem*)item)->p);
}


Может кто-то сталкивался???
Iron Bug
не выводи код ошибки в десятичном виде. перевод в шестнадцатиричный даёт нормальный читабельный код ошибки и по нему сразу всё понятно.
0xC0000005 - это ошибка обращения к памяти. классика жанра.
где-то кто-то обращается к удалённому объекту. или вылетает за границу массива. надо весь код смотреть, по куску не понять, что там удаляется зря.

RazrFalcon
PS: так выводит сам Qt Creator, по этому - увы
Iron Bug
Цитата(RazrFalcon @ 2.2.2013, 4:58) *
PS: так выводит сам Qt Creator, по этому - увы

садизм какой-то. причём неоправданный :D
Litkevich Yuriy
Цитата(demaker @ 1.2.2013, 17:59) *
void Widget::sl_deletePlot(QTreeWidgetItem*item,int column)
{
    qDebug()<<"sl_deletePlot";
    qDebug()<<"plot = "<<((TreeWidgetItem*)item)->p;

    ((TreeWidgetItem*)item)->p->deleteLater();    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    listPlot.removeOne(((TreeWidgetItem*)item)->p);
}
Можно получить комментарий, к каждой строчке? Я не понимаю того, что здесь делается.

Особенно интересует разбор этого:
((TreeWidgetItem*)item)->p
lanz
Ноосфера подсказывает мне что дело в двойном удалении item->p.

((TreeWidgetItem*)item)->p->deleteLater();    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
listPlot.removeOne(((TreeWidgetItem*)item)->p);


Сначала removeOne удаляет элемент, затем управление возвращается в event loop и выполняется удаление по deleteLater.
Можно попробовать убрать deleteLater.
Еще возможно, если item был создан с parent то parent его удалит (это будет уже третье удаление).

Для диагностики можно добавить печаталку в деструктор.
demaker
void Widget::sl_deletePlot(QTreeWidgetItem*item,int column)
{
    qDebug()<<"sl_deletePlot";

    if( (((TreeWidgetItem*)item)->checkState(0) == Qt::Checked) && (((TreeWidgetItem*)item)->p != NULL) )
    {
        qDebug()<<"plot = "<<((TreeWidgetItem*)item)->p;
        listPlot.removeOne(((TreeWidgetItem*)item)->p);
        ((TreeWidgetItem*)item)->p->deleteLater();
    }
}


((TreeWidgetItem*)item)->p // это указатель на плот, который принадлежит item


class Plot;
class TreeWidgetItem: public QObject, public QTreeWidgetItem
{
    Q_OBJECT

public:
    Plot* p;

public:
    explicit TreeWidgetItem(TreeWidgetItem*parent);
    explicit TreeWidgetItem(QTreeWidget*parent);
    explicit TreeWidgetItem(QTreeWidgetItem*parent);
    ~TreeWidgetItem();
};


и СООТВЕТСТВЕННО

   connect(tree,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),this,SLOT(sl_deletePlot(QTreeWidgetItem*,int)));


по коннектету
вызывается слот для удаления плота
Алексей1153
необходимость явного приведения - уже признак кривизны кода :)

((TreeWidgetItem*)item)->p

скажи, зачем это делаешь ?
demaker
Цитата(Алексей1153 @ 4.2.2013, 13:01) *
необходимость явного приведения - уже признак кривизны кода :)

((TreeWidgetItem*)item)->p

скажи, зачем это делаешь ?


Чтобы знать какому item принадлежит какой plot

((TreeWidgetItem*)item)->p
Потому что сигнал itemDoubleClicked(QTreeWidgetItem*,int) !!!QTreeWidgetItem
а у меня TreeWidgetItem
Алексей1153
demaker,
указатель item должен уметь рассказывать это без явного приведения. Либо через виртуальную функцию, либо через dynamic_cast, либо через стороннюю ассоциативную таблицу


Чтобы долго всем мозги догадками не компостировать, прицепи проект ))

demaker
Сча подцеплю

А что архив нельзя :blink:

Могу по файлу

У файлы не цепляет, может на мыло, если не против, то вышли
Алексей1153
zip архив

или сюда zalil.ru
demaker
Отправил на залил
архив(Rar) untitled

да и cfg-файл и dat-файл
тоже
сча скину на zalil

Все скинул :)
lanz
А мне ссылку на zalil?
demaker
Цитата(Алексей1153 @ 4.2.2013, 13:25) *
zip архив

или сюда zalil.ru


http://zalil.ru/34229242

Цитата(demaker @ 4.2.2013, 14:21) *
Цитата(Алексей1153 @ 4.2.2013, 13:25) *
zip архив

или сюда zalil.ru


http://zalil.ru/34229242
http://zalil.ru/34229246 -> cfg-файл
http://zalil.ru/34229254 -> dat-файл


Алексей1153
demaker, cfg и dat не нужны. Плоттер тоже - сделай так, чтобы было только дерево с проблемой. сразу туда добавь элементы. Чтобы просто запустить и увидеть падение
lanz
Заводится переменная:
data = new QwtPointArrayData(ct->getTimeDataVector(fn_dat+".DAT"),
                                     ct->getAnalogDataVector(fn_dat+".DAT", number_chanel),
                                     ct->DynamicCfg->NumSamples);


Дальше теряется ownership!
curve->setData(data);

Из документации:
Цитата
QwtPlotSeriesItem< T >::setData
Warning:
The item takes ownership of the data object, deleting it when its not used anymore.


Теперь удаляется data!
delete data;

А потом ее удаляет еще раз тот кто ей владеет(curve).
И соответственно падает, т.к. она вручную удалена в деструкторе Plot.

Надо удалить delete из деструктора Plot.
demaker
Цитата(lanz @ 4.2.2013, 15:03) *
Заводится переменная:
data = new QwtPointArrayData(ct->getTimeDataVector(fn_dat+".DAT"),
                                     ct->getAnalogDataVector(fn_dat+".DAT", number_chanel),
                                     ct->DynamicCfg->NumSamples);


Дальше теряется ownership!
curve->setData(data);

Из документации:
Цитата
QwtPlotSeriesItem< T >::setData
Warning:
The item takes ownership of the data object, deleting it when its not used anymore.


Теперь удаляется data!
delete data;

А потом ее удаляет еще раз тот кто ей владеет(curve).
И соответственно падает, т.к. она вручную удалена в деструкторе Plot.

Надо удалить delete из деструктора Plot.


Сделал как вы сказали, работает.
Но аналоговые плоты удаляет, а дескретные нет, точнее в дебаге удаляет, а если просто запустить то вылетает
с ошибкой
завершился с кодом 255

Или завершился с кодом -1073741819
lanz
А в каком месте вылетает?
demaker
Цитата(lanz @ 4.2.2013, 16:43) *
А в каком месте вылетает?


При удалении плота

void Widget::sl_deletePlot(QTreeWidgetItem*item,int column)
{
    qDebug()<<"sl_deletePlot";

    if( (((TreeWidgetItem*)item)->checkState(0) == Qt::Checked) && (((TreeWidgetItem*)item)->p != NULL) )
    {
        qDebug()<<"plot = "<<((TreeWidgetItem*)item)->p;
        listPlot.removeOne(((TreeWidgetItem*)item)->p);
        ((TreeWidgetItem*)item)->p->deleteLater();//!!!!!!!!!!!!!!!!!!!!!!!!!!
        ((TreeWidgetItem*)item)->setCheckState(0,Qt::Unchecked);
    }
}
lanz
То же самое.
Plot* plot = new Plot(c.Filename,c.type,c.channel_num,this);

Здесь plot становится дочерним виджетом widget, потом удаляется deleteLater, потом второй раз удаляется при удалении widget (т.к. входит в иерархию QObject-ов)

Надо удалить deleteLater.
Напомнило анекдот
"-Доктор, мне больно когда я вот-так делаю.
-Не делайте так. Следующий!"
:lol:
demaker
Согласен. Но также вылетает - 255 дает

Цитата(demaker @ 5.2.2013, 10:07) *
Согласен. Но также вылетает - 255 дает


Сделал так

void Widget::dropEvent(QDropEvent *event)
{
...

Plot* plot = new Plot(c.Filename,c.type,c.channel_num);
vbl_plot->addWidget(plot);
listPlot.append(plot);
...
}

Widget::~Widget()
{
    delete ui;

    for(int i = 0; i<listPlot.length();i++)
    {
        listPlot.at(i)->deleteLater();
    }
    listPlot.clear();

    items.clear();
}


но не помогает.
demaker
int TreeWidget::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
    _id = QTreeWidget::qt_metacall(_c, _id, _a);
    if (_id < 0)
        return _id;
    if (_c == QMetaObject::InvokeMetaMethod) {
        switch (_id) {
        case 0: sg_itemChecked((*reinterpret_cast< TreeWidgetItem*(*)>(_a[1]))); break;
        default:;
        }
        _id -= 1;
    }
    return _id;
}

вот в этой функции, когда в дебаге отлаживаю зависает и не выходит

хотя нет - но в дебаге работает нормально, а так :unsure: не понимаю почему
lanz
Ага, а deleteLater остался в sl_deletePlot? Хотя не должно влиять там они и из листа удаляются.
demaker
Цитата(lanz @ 5.2.2013, 13:05) *
Ага, а deleteLater остался в sl_deletePlot? Хотя не должно влиять там они и из листа удаляются.


В листе у нас вроде :blink: указатели на плоты, а не сами плоты.
Может я ошибаюсь :huh:

Поэтому мы по списку идем и удаляем.
Правильно?

 for(int i = 0; i<listPlot.length();i++)
    {
        listPlot.at(i)->deleteLater();
    }
    listPlot.clear();


а в слоте, я удаляю тот, на который кликнули

connect(tree,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),this,SLOT(sl_deletePlot(QTreeWidgetItem*,int)));


 listPlot.removeOne(((TreeWidgetItem*)item)->p);
((TreeWidgetItem*)item)->p->deleteLater();
lanz
Мне не нравятся эти deleteLater в деструкторе.
Виджет разрушается уже после выхода приложения из основного цикла, поэтому делет лэйтер может не сработать, да и вообще хз как он работает в завершившемся приложении. Можно попробовать тупо закомментить его, посмотреть что будет, если ошибка пройдет значит в нем дело.
demaker
Цитата(lanz @ 5.2.2013, 13:16) *
Мне не нравятся эти deleteLater в деструкторе.
Виджет разрушается уже после выхода приложения из основного цикла, поэтому делет лэйтер может не сработать, да и вообще хз как он работает в завершившемся приложении. Можно попробовать тупо закомментить его, посмотреть что будет, если ошибка пройдет значит в нем дело.


Закоментил

listPlot.removeOne(((TreeWidgetItem*)item)->p);
//((TreeWidgetItem*)item)->p->deleteLater();
((TreeWidgetItem*)item)->setCheckState(0,Qt::Unchecked);


при двойном клике на item, плот не закрывается, и не вылетает.
а когда виджет закрываю, то в консоле
untitled.exe завершился с кодом -1073741819

Вся фигня, когда я добавляю графики с цифровым сигналом(digital)
А с аналоговыми(analog) все нормально. :huh:
lanz
Не, не эти deleteLater .)

Вот эти
    for(int i = 0; i<listPlot.length();i++)
    {
        listPlot.at(i)->deleteLater();
    }

demaker
Не, все так же
Алексей1153
нужно:

1) решить, какой класс управляет данными в массиве (в частности - в мапе, в списке)
2) инкапсулировать массив в этот класс с доступом private
3) сделать методы Clear(), DeleteItem(), .... , AddItem(), FindItem(), ...
4) из конструктора класса вызвать Clear()

и не мучать себя и остальных :D

и, естественно, никаких deleteLater
demaker
Цитата(Алексей1153 @ 5.2.2013, 14:48) *
нужно:

1) решить, какой класс управляет данными в массиве (в частности - в мапе, в списке)
2) инкапсулировать массив в этот класс с доступом private
3) сделать методы Clear(), DeleteItem(), .... , AddItem(), FindItem(), ...
4) из конструктора класса вызвать Clear()

и не мучать себя и остальных :D

и, естественно, никаких deleteLater


:) ок -> понял


И еще такой вопрос по поводу deleteLater.

Как мне удалить график, который я добавил на виджет?
Чуть подробнее можно. :)
Алексей1153
как удалить - это зависит от того, как добавлял.

К примеру, ты в какой-то момент времени создаёшь на куче через new и добавляешь к плоттеру (теперь плоттер САМ заботится об удалении графика - в деструкторе это произойдёт) . Если ты извлёк график (навроде removeitem) , то плоттер уже не заботится о его судьбе. Ты можешь сразу после извлечения удалить память графика при помощи delete - так как сам он не удалится. Но это просто утечка памяти, а не выпадение

Придерживайся правила - где создал объект, там и удаляй.
В одном классе.
В двух методах одного класса (create/delete).
В одном методе (на стеке, к примеру) .
В одном потоке. Не надо делать так - в одном потоке создал, в другом удалил.
В одном процессе.

Это желательно :) Так меньше ошибок
lanz
Так, а ларчик просто открывался :lol:
Все падает в ~CCOMTRADE, когда удаляются неинициализированные
    if(TimeDataVector != NULL) delete[] TimeDataVector;
    if(AnalogDataVector != NULL) delete[] AnalogDataVector;
    if(DigitalDataVector != NULL) delete[] DigitalDataVector;


Лечится добавлением в конструктор
TimeDataVector = NULL;
AnalogDataVector = NULL;
DigitalDataVector = NULL;


Но вообще Алексей1153 дело говорит.
И еще поменьше new/delete, а вместо них побольше QVector-ов.
Алексей1153
ну, или std::vector / std::map (лично я кутешные контейнеры стараюсь не использовать, если только никак без этого)

тогда такие забывания просто не существуют
demaker
Понятно, спасибо.
Но у меня вроде так и есть:

деструктор:
Widget::~Widget()
{
    for(int i = 0; i<listPlot.length();i++)
    {
        listPlot.at(i)->deleteLater();
    }
    listPlot.clear();

    items.clear();

    delete ui;
}

одиночное удаление:
void Widget::sl_deletePlot(QTreeWidgetItem*item,int column)
{
    qDebug()<<"sl_deletePlot";

    if( (((TreeWidgetItem*)item)->checkState(0) == Qt::Checked) && (((TreeWidgetItem*)item)->p != NULL) )
    {
        qDebug()<<"plot = "<<((TreeWidgetItem*)item)->p;
        listPlot.removeOne(((TreeWidgetItem*)item)->p);
        ((TreeWidgetItem*)item)->p->deleteLater();
        ((TreeWidgetItem*)item)->setCheckState(0,Qt::Unchecked);
    }
}

и создание:
void Widget::dropEvent(QDropEvent *event)
{
    if (event->mimeData()->hasFormat("application/x-qt-windows-mime;value=\"ComtradeChannel\""))
    {
        QByteArray d(event->mimeData()->data("application/x-qt-windows-mime;value=\"ComtradeChannel\""));

        if (d != QVariant(-1).toByteArray())
        {
            qDebug()<<"d = "<<d;
            comtrade_curve_t c= possible_curves.at(d.at(0));

            qDebug()<<c.Filename;
            qDebug()<<c.type;
            qDebug()<<c.channel_num;
            event->acceptProposedAction();

            Plot* plot = new Plot(c.Filename,c.type,c.channel_num,0);
            vbl_plot->addWidget(plot);
            listPlot.append(plot);

            qDebug() <<"number = "<<index;
            plot->item = items.at(index);
            items.at(index)->p = plot;
            qDebug() <<"plot = "<<items.at(index)->p;
        }
        else
        {
        }
    }
}


Не могу понять что нето. :unsure:
Спасибо.
Попробую заново переписать.
Алексей1153
вот это
        listPlot.removeOne(((TreeWidgetItem*)item)->p);
        ((TreeWidgetItem*)item)->p->deleteLater();
        ((TreeWidgetItem*)item)->setCheckState(0,Qt::Unchecked);

должно выглядеть так (в первом приближении)
     listPlot.removeOne(item);
     item->delete_my_p();
//delete item; возможно, это тоже тут


...::delete_my_p()
{
      delete p;
      p=0;
}
demaker
Понятно.

Ну в item должен быть указатель на plot
за этим я и создал TreeWidgetitem от QTreeWidgetitem

но сигнал itemDoubleClicked(QTreeWidgetItem*,int) передает только QTreeWidgetItem*, поэтому приходится делать явное преобразование типов ((TreeWidgetItem*)item)->p

lanz, Алексей1153 огромное спасибо ВАМ!!!
Алексей1153
demaker, не должно быть таких преобразований. Что-то не так делаешь
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.