Russian Qt Forum

Qt => Общие вопросы => Тема начата: xintrea от Январь 17, 2016, 01:31



Название: Почему сегфолт в деструкторе?
Отправлено: xintrea от Январь 17, 2016, 01:31
Имею класс, в котором создается виджет таблицы 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/825956/scr_374.png

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

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


Название: Re: Почему сегфолт в деструкторе?
Отправлено: Bepec от Январь 17, 2016, 02:47
Ну во 1 вы не привели код создания table (точнее привели кусок, а место не привели).
во 2 - вы делаете плохую бяку. Вы удаляете итем, при этом table свято уверен что итем остался.
в 3 - то же самое с прогрессбаром.
в 4 - приведите значение i. Скорее всего сегфолт вылетает эдак на 2-3, мб даже больше итерации цикла.
в 5 - вы указали table родителя. То есть родитель сам удалит ваш table.
в 6 - приводите весь код :)

PS дебаггер в руки и точку остановки на деструктор table. Так и разберётесь.


Название: Re: Почему сегфолт в деструкторе?
Отправлено: Old от Январь 17, 2016, 06:58
2 xintrea
А покажите весь стек возвратов.

2 Bepec
Вы сообщения вообще читать перестали? Написали кучу притензий, а они все раскрыты в сообщении...


Название: Re: Почему сегфолт в деструкторе?
Отправлено: Bepec от Январь 17, 2016, 08:50
to Old:
По пунктам
1. нет места в коде, где кусок создания находится. Т.е. понять где он создаётся и при каких обстоятельствах хз.
2,3,4 - не раскрыто от слова вообще
5. Без комментариев.
6. Без комментариев.

Где тут раскрытость всех пунктов?

И да добавлю - то что объект существует не значит, что он там есть. Он может быть уже удалён, просто данные не затерты.


Название: Re: Почему сегфолт в деструкторе?
Отправлено: Old от Январь 17, 2016, 09:46
1. нет места в коде, где кусок создания находится. Т.е. понять где он создаётся и при каких обстоятельствах хз.
А какая разница, в каком месте создается объект? Главное что он создается.

2,3,4 - не раскрыто от слова вообще
Если итема или прогресбара нет, то вернется nullptr, а delete с этим легко справляется. Из-за этого ничего падать не будет. К тому-же падение происходит раньше.
По поводу 4 пункта, откройте картинку и посмотрите, там есть ответы на все ваши вопросы. Ну и ТС четко написал на какой итерации происходит падение.

5. Без комментариев.
Не имеет значение, указал он родителя или не указал. Он всегда сможет удалить объект руками.

6. Без комментариев.
ТС не раз приводил ссылки на github со своим проектом. Если бы он был вам нужен, вы бы легко его нашли: https://github.com/xintrea/mytetra_dev


Название: Re: Почему сегфолт в деструкторе?
Отправлено: __Heaven__ от Январь 17, 2016, 12:49
Попробуйте пересобрать проект. У меня не вылетает сегфолта. Валгринд выдаёт только утечки памяти, но это не влияет на сегфолт


Название: Re: Почему сегфолт в деструкторе?
Отправлено: Igors от Январь 17, 2016, 13:40
Если "вылетает стабильно", то это не проблема. Я бы "покрутил" немного, напр так

1) Вставить в тело цикла
Код
C++ (Qt)
qDebug() << "deleting" << i << "of" << table->rowCount();

2) Закомментировать оба delete в цикле, потом по одному

3) Ну и "Rebuild All" (как уже советовали) тоже лишним не будет

Обычно после таких простых действий ситуевина быстро проясняется




Название: Re: Почему сегфолт в деструкторе?
Отправлено: Bepec от Январь 17, 2016, 14:06
Кто то где то порушил память скорее всего. А вылет уже следствие.

Никаких новых работ с массивами информации не добавляли?

to Old: чесслово я помню только 1 человека с проектом и это QSerialPort. Остальное как то не отложилось :D


Название: Re: Почему сегфолт в деструкторе?
Отправлено: xintrea от Январь 17, 2016, 14:28
PS дебаггер в руки и точку остановки на деструктор table. Так и разберётесь.

Разобрался. Я опять забыл что указал родителя (this) при создании QTableWidget. И при delete table у меня шло двойное удаление объекта.


Название: Re: Почему сегфолт в деструкторе?
Отправлено: xintrea от Январь 17, 2016, 14:35
Попробуйте пересобрать проект. У меня не вылетает сегфолта. Валгринд выдаёт только утечки памяти, но это не влияет на сегфолт

С какими опциями запускали valgrind? У меня он показывает утечки даже в библитечных методах. Если несложно, покажите опции и лог валгринда на http://pastebin.com.


Название: Re: Почему сегфолт в деструкторе?
Отправлено: Old от Январь 17, 2016, 14:52
Разобрался. Я опять забыл что указал родителя (this) при создании QTableWidget. И при delete table у меня шло двойное удаление объекта.
Не может этого быть. Из-за этого не бывает двойного удаления.


Название: Re: Почему сегфолт в деструкторе?
Отправлено: __Heaven__ от Январь 17, 2016, 14:56
С какими опциями запускали valgrind? У меня он показывает утечки даже в библитечных методах. Если несложно, покажите опции и лог валгринда на http://pastebin.com.
Я его запускаю из qtcreator, а там уже можно фильтр настроить, чтобы не показывал внешние ошибки.


Название: Re: Почему сегфолт в деструкторе?
Отправлено: __Heaven__ от Январь 17, 2016, 15:00
Разобрался. Я опять забыл что указал родителя (this) при создании QTableWidget. И при delete table у меня шло двойное удаление объекта.
Дополню комментарий old.
У вас при "первом" удалении посылается сигнал родителю о том, что объект ликвидирован. Таким образом родитель не станет второй раз освобождать память.


Название: Re: Почему сегфолт в деструкторе?
Отправлено: xintrea от Январь 17, 2016, 15:24
Я его запускаю из qtcreator, а там уже можно фильтр настроить, чтобы не показывал внешние ошибки.

Сделайте, пожалусто, скриншот фильтров valgrind (проще положить на piccy.info).

И лог на pastebin.com.


Название: Re: Почему сегфолт в деструкторе?
Отправлено: __Heaven__ от Январь 17, 2016, 16:22
Картинка (http://piccy.info/view3/9283570/8f46d5151381229076fa91ac6e612737/orig/). Как из creator экспортировать лог - не знаю. В терминале лог засоряется дебажными сообщениями из приложения и как переправить валгридовский выхлоп в файл тоже не знаю. Проверку в терминале запускаю с помощью
Код:
valgrind --leak-check=full ./mytetra
Зато знаю, как в xml формате заставить валгрид записывать. Во вложении отчёт, который можно открыть в qtcreator на вкладке анализа.


Название: Re: Почему сегфолт в деструкторе?
Отправлено: __Heaven__ от Январь 17, 2016, 16:31
А что значит запись?
class EditorToolBar : public QWidget
{
public:
  // ...
  QToolButton   *bold=NULL;    // <==
  //...
};
У меня компиль выдаёт предупреждение
Цитировать
in-class initialization of non-static data member is a C++11 extension [-Wc++11-extensions]
и я её не понимаю.


Название: Re: Почему сегфолт в деструкторе?
Отправлено: __Heaven__ от Январь 17, 2016, 16:32
Кажется имеется в виду, что это фича из стандарта c++11, а проект не настроен на c++11


Название: Re: Почему сегфолт в деструкторе?
Отправлено: xintrea от Январь 17, 2016, 16:36
Благодарю, буду разбираться. Я такой сжатый отчет никак не мог получить.


Название: Re: Почему сегфолт в деструкторе?
Отправлено: __Heaven__ от Январь 17, 2016, 16:38
xintrea, я уже писал в ЛС, но вы не ответили. Можно ваш скайп?


Название: Re: Почему сегфолт в деструкторе?
Отправлено: xintrea от Январь 17, 2016, 16:40
А что значит запись?

  QToolButton   *bold=NULL;    // <==

Я долго разбирался с этим:

Почему в заголовке можно инициализировать тип указателя, но нельзя инитить переменные? (https://www.linux.org.ru/forum/development/12239055)

К однозначному выводу не пришли. Вроде как для указателей это можно делать.



Название: Re: Почему сегфолт в деструкторе?
Отправлено: xintrea от Январь 17, 2016, 16:43
xintrea, я уже писал в ЛС, но вы не ответили. Можно ваш скайп?

Ответил. Мне раз два года если кто пишет, то хорошо, вообще на личку внимания не обращаю.


Название: Re: Почему сегфолт в деструкторе?
Отправлено: xintrea от Январь 17, 2016, 16:50
Кажется имеется в виду, что это фича из стандарта c++11, а проект не настроен на c++11

Я когда разбирался, понял, что правильнее будет пользоваться списком инициализации.

Но со списком инициализации все не слава богу. В нем нужно следить за порядком инициализации. Если порядок инициализации будет не соответствовать порядку определений в классе, будут феерические глюки:

Код:
class Test {
    // Порядок объявления членов класса
    int b;
    int a;
public:
    Test(int x) : a(x), b(a) {}; // Нарушен порядок
};

Создавать еще одну точку возможного отказа как-то не хочется.


Название: Re: Почему сегфолт в деструкторе?
Отправлено: Igors от Январь 17, 2016, 17:37
..будут феерические глюки:
Примерчик наверняка с хабра - меньше читайте эту муть  :)