Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: Disaron от Февраль 14, 2013, 08:19



Название: Unhandled exception при QFile::copy
Отправлено: Disaron от Февраль 14, 2013, 08:19
Привет всем.

Собственно сабж на котором сломал голову. Есть многопоточная прога, которая в несколько потоков перекладывает файлы между разными ресурсами.
Вся беда в том, что в один прекрасный момент она вылетает к хренам и я никак не могу отловить на какой стадии. Может 100 раз переложить одни и те-же файлы, а может 3 и вылететь. Дебаг показывает сегфолт и смерть потока (последнее время вообще gdb отказывается запускаться - разбираюсь). Весь процесс c файлами происходит в TaskExecuter.

ЗЫ: Замечено, что в это время наблюдается активность монитора антивируса - может в этом дело, но тогда это баг Qt? Или все-таки я недостаточно еще знаком со всеми подводными камнями MT и где-то дико накосячил?

В общем прошу помощи у аудитории, я уже, чувствую, замылил взгляд...

XP + Qt 4.8.4 + MinGW.


Название: Re: Unhandled exception при QFile::copy
Отправлено: carrygun от Февраль 14, 2013, 08:57
Старый GDB может не работать в новом креаторе, сам сталкивался с таким. Либо не запускался, либо крашился на дебаге.
Новый можно скачать с новым мингв (но как инструментарий придется все равно использовать старый, если не лень пересобирать кутэ), либо можно скачать подсунуть отдельно GDB.


Название: Re: Unhandled exception при QFile::copy
Отправлено: Disaron от Февраль 18, 2013, 22:04
Старый GDB может не работать в новом креаторе, сам сталкивался с таким. Либо не запускался, либо крашился на дебаге.
Новый можно скачать с новым мингв (но как инструментарий придется все равно использовать старый, если не лень пересобирать кутэ), либо можно скачать подсунуть отдельно GDB.
Спасибо. Завел отладчик и проблема, как выяснилось, была совсем не в бобине, а вот в этом коде:

Код
C++ (Qt)
QList<JobData>::iterator it = m_jobList.begin();
while (it != m_jobList.end()) {
   if ((*it).state == JS_DONE) {
       m_jobList.removeOne(*it);
   }
   ++it;
}
//И как вообще такое в голову пришло?!

Замена на некошерный
Код
C++ (Qt)
foreach (JobData jb, m_jobList) {
   if (jb.state == JS_DONE)
       m_jobList.removeAt(m_jobList.indexOf(jb));
}
 
работает.


Название: Re: Unhandled exception при QFile::copy
Отправлено: carrygun от Февраль 19, 2013, 05:18
Для кутэшных контейнеров foreach и не такая уж плохая штука.


Название: Re: Unhandled exception при QFile::copy
Отправлено: GreatSnake от Февраль 19, 2013, 07:57
Для кутэшных контейнеров foreach и не такая уж плохая штука.
Только вот эту штуку не мешало бы с умом применять, а не как автор.


Название: Re: Unhandled exception при QFile::copy
Отправлено: Пантер от Февраль 19, 2013, 08:02
Я бы std::remove_if заюзал. :)


Название: Re: Unhandled exception при QFile::copy
Отправлено: Igors от Февраль 19, 2013, 08:10
Код
C++ (Qt)
foreach (JobData jb, m_jobList) {
   if (jb.state == JS_DONE)
       m_jobList.removeAt(m_jobList.indexOf(jb));
}
 
Зачем использовать затратный indexOf, лучше так
Код
C++ (Qt)
int i = 0;
while (i < m_jobList.size()) {
   if (m_jobList[i].state == JS_DONE)
       m_jobList.removeAt(i);
   else
       ++i;
}
 
Для кутэшных контейнеров foreach и не такая уж плохая штука.
Лично я не вижу в нем ничего хорошего. Конечно пользоваться никто не заставляет, дело вкуса

Я бы std::remove_if заюзал. :)
В данном случае remove_if не очень хорошо  :)


Название: Re: Unhandled exception при QFile::copy
Отправлено: Пантер от Февраль 19, 2013, 08:28
Я бы std::remove_if заюзал. :)
В данном случае remove_if не очень хорошо  :)
Почему?


Название: Re: Unhandled exception при QFile::copy
Отправлено: Igors от Февраль 19, 2013, 08:43
Почему?
Код с removeAt удаляет объекты и сдвигает хвост массива указателей (внутри QList). А remove_if переставляет/обменивает сами элементы вызывая оператор присваивания. Это куда хуже для элементов - приличных структур.


Название: Re: Unhandled exception при QFile::copy
Отправлено: Igors от Февраль 19, 2013, 09:18
Строго говоря и removeAt не оптимально. Думаю правильно так
Код
C++ (Qt)
#include <QtGui>
 
template <class T, class TShouldDel>
void QListRemoveIf( QList<T> & lst, TShouldDel shouldDel )
{
int i = 0, last = lst.size();
while (i < last) {
if (shouldDel(lst[i]))
lst.swap(i, --last);
else
++i;
}
 
lst.erase(lst.begin() + last, lst.end());
}
 
bool MyShouldDel( int val )
{
return val == 1;
}
 
int main( void )
{
QList <int> test;
test << 2 << 3 << 1 << 9;
qDebug() << test;
 
QListRemoveIf(test, MyShouldDel);
qDebug() << test;
 
return 0;
}
 
QList::swap - умный метод, переставляет только указатели

Update: и кстати о птичках - после такого удаления адреса всех оставшихся элементов не меняются


Название: Re: Unhandled exception при QFile::copy
Отправлено: Пантер от Февраль 19, 2013, 10:34
На больших наборах данных согласен.


Название: Re: Unhandled exception при QFile::copy
Отправлено: twp от Февраль 19, 2013, 15:04
а чем не подошел erase?
Код
C++ (Qt)
QList<JobData>::iterator it = m_jobList.begin();
while (it != m_jobList.end()) {
   if ((*it).state == JS_DONE)
       it = m_jobList.erase(it);
   else
       ++it;
}
 


Название: Re: Unhandled exception при QFile::copy
Отправлено: Disaron от Февраль 21, 2013, 21:12
Зачем использовать затратный indexOf, лучше так
Код
C++ (Qt)
int i = 0;
while (i < m_jobList.size()) {
   if (m_jobList[i].state == JS_DONE)
       m_jobList.removeAt(i);
   else
       ++i;
}
 

Лучше, с т.з. затрат - в последнем варианте так и есть. Там вообще много чего по-другому, включая конструирование потоков "по фэн-шуй".
Кстати человеку, первый раз читающему код на Qt-контейнерах, совсем не очевидно, что removeAt сдвигает массив, поэтому возникнет вопрос "а почему оно работает?". Придется лезть в доки, а то и в код Qt. Мне, пишущему от случая к случаю, да на коленке, и то пришлось вспомнить это.
Вопрос производительности на момент исправления не стоял - был вопрос быстрого исправления бага.

Но это так - отмазки... :)

ЗЫЖ foreach ИМХО этакий удобный костыль, с которого потом надо лишний раз слезать, жду повсеместной поддержки for (T x : list<T>) {}


Название: Re: Unhandled exception при QFile::copy
Отправлено: carrygun от Февраль 22, 2013, 05:19
ЗЫЖ foreach ИМХО этакий удобный костыль, с которого потом надо лишний раз слезать, жду повсеместной поддержки for (T x : list<T>) {}

А разве последний мингв не умеет?


Название: Re: Unhandled exception при QFile::copy
Отправлено: Disaron от Февраль 22, 2013, 06:32
А разве последний мингв не умеет?
Умеет, и не только последний. Но его прикрутить надоть, скачать - а это лень...  ;D