LINUX.ORG.RU

Почему сегфолт в деструкторе?

 ,


0

2

Имею класс, в котором создается виджет таблицы QTableWidget, указатель на который хранится в свойстве table:

table=new QTableWidget(0, colsName.count(), this);
table->setHorizontalHeaderLabels(colsName);


В процессе работы класса в таблицу добавляются строки. Ячейки строк заполняются QTableWidgetItem * или виджетами, вставляемыми через QTableWidget::setCellWidget();

В деструкторе необходимо пробежать всю таблицу и удалить итемы и вставленные виджеты.

Я это делаю так:

Downloader::~Downloader()
{
  // Удаляется содержимое таблицы
  for(int i=0; i<table->rowCount(); i++) // <-- Тут сегфолт!
  {
    delete table->item(i, downloadReferenceCol);
    delete qobject_cast<QProgressBar *>( table->cellWidget(i, downloadReferenceCol) );
  }

  delete table;
  delete cancelButton;
}


Но получаю сегфолт на строке с циклом при выполнении самой первой итерации.

Скриншот:

http://i.piccy.info/i9/053bea8edbb2549fea811c231e4af339/1452982758/389884/825...

Видно, что table существует, и содержит какой-то адрес. Но выражение table->rowCount() почему-то не высчитывается. И получается сегфолт.

Вопрос: из-за чего появляется такой сегфолт?

★★★★★
Ответ на: комментарий от Xintrea

доступ к базовому объекту возможен просто по указателю на производный класс

да

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

Ему и не надо знать. Если у него есть метод foo, то он гарантированно есть у всех производных, так что можно вызывать и не париться.

И я ума не приложу, с какой целью люди пишут так

Например, ты можешь сделать контейнер типа QWidget* и сложить туда любые виджеты, и обходя контейнер вызывать любые методы QWidget, не заботясь о реальном типе каждого виджета.

anonymous
()
Ответ на: комментарий от Xintrea

И я ума не приложу, с какой целью люди пишут так:

Base* bp = new Derived;
Вместо естественного
Derived* bp = new Derived;
Зачем такая путанница нужна?

Вот захочешь завтра добавить пару-тройку очередных SuperNewDerived с какой-то особой, расширенной логикой - и поймешь зачем.

Suigintou ★★★★★
()
Ответ на: комментарий от Xintrea

объекты Qt спроектированы так, что без ручного управления не обойтись.

Что, в qt нет smart pointer-ов? Серьезно?

Pinkbyte ★★★★★
()
Ответ на: комментарий от Xintrea

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

Вывод - книги в этом плане говно. Я такие тоже в своё время читал. Пока не понял, что по ним можно освоить только что-то в стиле «как написать hello world и не облажаться». А дальше - надо курить стандарт и библиотеки. Самому.

Pinkbyte ★★★★★
()
Ответ на: комментарий от Xintrea

Каким образом delete выводит тип Derived *, если ей передается указатель с типом Base * ?

Не совсем в тему, но

google://RTTI

Pinkbyte ★★★★★
()

Извиняюсь, но зачем вообще ломать себе голову плюсами, если это не основное занятие. Проще взять PyQt и сделать сразу то что нужно, сэкономив кучу нервов и здоровья.

anonymous
()
Ответ на: комментарий от Xintrea

И я ума не приложу, с какой целью люди пишут так:
Base* bp = new Derived;
Вместо естественного
Derived* bp = new Derived;

Так писать не нужно, ты прав. Возможно автор оставил это чтобы потом прикрутить фабрику:

CBase *fabricGiveMeObject()
{
    if (today == sunday)
        return new CDerived1();
    else if (today == monday)
        return new CDerived2();
    else
        return new CDerived3();
}

CBase *p = fabricGiveMeObject();
JANB
()
Ответ на: комментарий от Xintrea

Каким образом delete выводит тип Derived *, если ей передается указатель с типом Base * ?

Читай про виртуальные деструкторы, хоть на той же википедии. Твой вопрос абсолютно классический.

JANB
()
Ответ на: комментарий от Xintrea

Упростил деструктор до такого примитива:
И имею сегфолт на delete table.

Вангую, что знаю что у тебя за ошибка!

Код конструктора в студию, где создается table!

JANB
()
Ответ на: комментарий от Suigintou

Вот захочешь завтра добавить пару-тройку очередных SuperNewDerived с какой-то особой, расширенной логикой - и поймешь зачем.

Скорее всего, завтра не захочу, а захочу через несколько лет.

Но лучше, чтобы ты объяснил уже сейчас, что я должен понять.

Маленький сжатый пример и пояснение на русском нематерном улучшат ситуацию.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от JANB

// Каким образом delete выводит тип Derived *, если ей передается указатель с типом Base * ?

// Читай про виртуальные деструкторы, хоть на той же википедии. Твой вопрос абсолютно классический.

Виртуальные деструкторы к выводу типа не имеют никакого отношения. Тут вопрос в vtable.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Извиняюсь, но зачем вообще ломать себе голову плюсами, если это не основное занятие. Проще взять PyQt и сделать сразу то что нужно, сэкономив кучу нервов и здоровья.

У Qt выше кроссплатформенность и скорость работы. Моя программа собирается даже под Android и спокойно работает на ARM без костылей и лагов.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Каким образом delete выводит тип Derived *, если ей передается указатель с типом Base * ?

Читай про виртуальные деструкторы, хоть на той же википедии. Твой вопрос абсолютно классический.

Виртуальные деструкторы к выводу типа не имеют никакого отношения. Тут вопрос в vtable.

«Виртуальный» имеет отношение к выводу типа.
«деструктор» имеет отношение к delete.

С чем ты споришь, непонятно.

vtable

Ну, да. Виртуальные функции имеют отношение к vtable.

JANB
()
Ответ на: комментарий от Xintrea

Еще раз - или выложи код конструктора где создается table, или помечай тему как решенную, если у тебя уже всё работает.

JANB
()
Ответ на: комментарий от JANB

«Виртуальный» имеет отношение к выводу типа.

я то думал оно для связывания методов, а оно вон оно как - типы, понимаешь, выводит, новости кругом

shty ★★★★★
()
Последнее исправление: shty (всего исправлений: 1)
Ответ на: комментарий от Xintrea

Если посмотреть на гитхаб, то можно увидеть, что зачастую у меня проходит пара недель или даже месяц между моментом, когда внесено изменение в код, и моментом, когда код вообще начал компилироваться. Попробуй поработать в таком режиме. Это ужасно.

Я попадаю «в поток» либо в отпуске, либо на новогодних праздниках. Две недели уходит на то, чтобы нормально вспомнить что у меня там понаделано и уместить структуру в голове. К концу двух недель незанятости я наконец то вспоминаю что к чему в проекте, немножко вспоминаю как что делать в C++. Ирония в том, что отпуск дают только на 2 недели и новогодние праздники тоже примерно 2 недели. К моменту, когда я готов что-то делать, на меня сваливается работа, за которую мне платят деньги, и я быстро съезжаю к нуливому уровню.

зачем так жить?

shty ★★★★★
()
Ответ на: комментарий от Xintrea

а почитай ка для начала «C++ для профессионалов», там как раз аккуратно по полочкам разжевано все, что необходимо минимально знать, чтобы на базовом уровне работать с C++

shty ★★★★★
()
Последнее исправление: shty (всего исправлений: 1)
Ответ на: комментарий от anonymous

5 звезд на ЛОРе. Что за хрень?

Звёзды куплены!

rupert ★★★★★
()
Ответ на: комментарий от shty

Фраза «вывод типа» это цитата из сообщения ТСа. Я отвечал на его сообщения его цитатами. Посмотрите дискуссию И не цепляйтесь к словам, разумеется там нет никакого вывода типа.

JANB
()
Ответ на: комментарий от Xintrea

что я должен понять.

Полиморфизм и наследование в ООП в C++.

Suigintou ★★★★★
()
Ответ на: комментарий от Xintrea

А надо было читать Брюса Эккеля, «Философия С++», двухтомник. Заодно про паттерны там же почитайте.

next_time ★★★★★
()
Ответ на: комментарий от Xintrea

даже если бы таблица не умела удалять объекты самостоятельно, всегда можно создать vector<> или array<> объектов и передавать ссылку на объект из vector-а. объекты удалятся вместе с вектором сами.

next_time ★★★★★
()
Ответ на: комментарий от Xintrea

Про это тоже у Эккеля почитайте.

anonymous
()
21 октября 2016 г.
Ответ на: комментарий от i-rinat

Удаляет ли ClearContent QWidgetы или только QTableItemы

Собственн код, удаляющий содержимое QTableWidget.

QVector<QTableWidgetItem*> tableItems;

void QTableModel::clearContents() { beginResetModel(); for (int i = 0; i < tableItems.count(); ++i) { if (tableItems.at(i)) { tableItems.at(i)->view = 0; delete tableItems.at(i); tableItems = 0; } } endResetModel(); }

Из него видно, что он удаляет только элементы типа QTableWidgetItem. Элементы типа QWidget добавленные функцией setCellWidget clearContent не удаляет. Тем не менее, в описании указано что setCellWidget делает овнером такого виджета таблицу.

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

Если же строки добавлять с помощью setItem, то clearContent будет удалять такие itemы сразу.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.