Russian Qt Forum
Октябрь 04, 2024, 16:24 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Unhandled exception при QFile::copy  (Прочитано 7913 раз)
Disaron
Гость
« : Февраль 14, 2013, 08:19 »

Привет всем.

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

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

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

XP + Qt 4.8.4 + MinGW.
Записан
carrygun
Гость
« Ответ #1 : Февраль 14, 2013, 08:57 »

Старый GDB может не работать в новом креаторе, сам сталкивался с таким. Либо не запускался, либо крашился на дебаге.
Новый можно скачать с новым мингв (но как инструментарий придется все равно использовать старый, если не лень пересобирать кутэ), либо можно скачать подсунуть отдельно GDB.
Записан
Disaron
Гость
« Ответ #2 : Февраль 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));
}
 
работает.
Записан
carrygun
Гость
« Ответ #3 : Февраль 19, 2013, 05:18 »

Для кутэшных контейнеров foreach и не такая уж плохая штука.
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #4 : Февраль 19, 2013, 07:57 »

Для кутэшных контейнеров foreach и не такая уж плохая штука.
Только вот эту штуку не мешало бы с умом применять, а не как автор.
Записан

Qt 5.11/4.8.7 (X11/Win)
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #5 : Февраль 19, 2013, 08:02 »

Я бы std::remove_if заюзал. Улыбающийся
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Февраль 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 не очень хорошо  Улыбающийся
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #7 : Февраль 19, 2013, 08:28 »

Я бы std::remove_if заюзал. Улыбающийся
В данном случае remove_if не очень хорошо  Улыбающийся
Почему?
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Февраль 19, 2013, 08:43 »

Почему?
Код с removeAt удаляет объекты и сдвигает хвост массива указателей (внутри QList). А remove_if переставляет/обменивает сами элементы вызывая оператор присваивания. Это куда хуже для элементов - приличных структур.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Февраль 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: и кстати о птичках - после такого удаления адреса всех оставшихся элементов не меняются
« Последнее редактирование: Февраль 19, 2013, 09:23 от Igors » Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #10 : Февраль 19, 2013, 10:34 »

На больших наборах данных согласен.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
twp
Гость
« Ответ #11 : Февраль 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;
}
 
Записан
Disaron
Гость
« Ответ #12 : Февраль 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>) {}
« Последнее редактирование: Февраль 21, 2013, 22:13 от Disaron » Записан
carrygun
Гость
« Ответ #13 : Февраль 22, 2013, 05:19 »

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

А разве последний мингв не умеет?
Записан
Disaron
Гость
« Ответ #14 : Февраль 22, 2013, 06:32 »

А разве последний мингв не умеет?
Умеет, и не только последний. Но его прикрутить надоть, скачать - а это лень...  Смеющийся
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.218 секунд. Запросов: 23.