Russian Qt Forum

Программирование => С/C++ => Тема начата: __Heaven__ от Август 01, 2018, 09:46



Название: Отлов ошибки
Отправлено: __Heaven__ от Август 01, 2018, 09:46
Привет друзья!
Столкнулся с проблемой, что на одной машине программа выполняет некорректный расчёт. Подключиться к ней нет возможности...
Пробовал воспроизвести проблему под санитайзерами и valgrind - ругань только на сторонние либы и не в момент интересующего меня расчёта.
Входные данные примерно одинаковые (могут отличаться настройки отображения элементов отрисовки и положение клика пользователя)
Как только добавляю больше логов, чтобы локализовать проблему на проблемной машине, как она сразу пропадает.
Быть может кто-нибудь подкинет идей что можно ещё попробовать сделать для решения проблемы...


Название: Re: Отлов ошибки
Отправлено: Пантер от Август 01, 2018, 10:16
Что у тебя задействовано в расчете?
У меня как-то был косяк на одной машине из-за того, что использовалась Cuda, а дрова на видюху стояли какие-то кривые...


Название: Re: Отлов ошибки
Отправлено: Old от Август 01, 2018, 10:24
Нужно искать не инициализированные переменные. :)


Название: Re: Отлов ошибки
Отправлено: Пантер от Август 01, 2018, 10:37
Нужно искать не инициализированные переменные. :)
Которых априори быть не должно.


Название: Re: Отлов ошибки
Отправлено: Igors от Август 01, 2018, 12:53
.. некорректный расчёт.
Т.е. вылета нет, некорректный рез-т? Ну тогда для начала лог: входные данные + рез-т.


Название: Re: Отлов ошибки
Отправлено: __Heaven__ от Август 01, 2018, 13:23
Что у тебя задействовано в расчете?
У меня как-то был косяк на одной машине из-за того, что использовалась Cuda, а дрова на видюху стояли какие-то кривые...

В расчёте задействованы матрицы, точки из Qt также мои классы геометрии (плоскость, линия, треугольник). Клик берётся из QOpenGLWidget, но вроде корректные значения выставляются.

Нужно искать не инициализированные переменные. :)
Это первое, о чём подумал. Глазками пробежался - вроде нет. Стараюсь не допускать таких Мне кажется, валгринд бы ругнулся на неинициализированную переменную. А может существует ключик gcc/clang инициализировать неинициализированные переменные фиксированным значением?

.. некорректный расчёт.
Т.е. вылета нет, некорректный рез-т? Ну тогда для начала лог: входные данные + рез-т.
Текущего лога недостаточно. При подробном логгировании не воспроизводится


Название: Re: Отлов ошибки
Отправлено: __Heaven__ от Август 01, 2018, 13:30
Ещё есть момент - на той машине 2 монитора. Но, вроде, это никак не влияет

Код
C++ (Qt)
Converting user click: QPoint(389,671) to line


Название: Re: Отлов ошибки
Отправлено: Пантер от Август 01, 2018, 13:31
Потоки используются?


Название: Re: Отлов ошибки
Отправлено: zhbr от Август 01, 2018, 14:07
как вариант - прогнать код через статический анализатор кода(pvs или clang).


Название: Re: Отлов ошибки
Отправлено: __Heaven__ от Август 01, 2018, 15:55
Потоки используются?
openmp


Название: Re: Отлов ошибки
Отправлено: __Heaven__ от Август 01, 2018, 15:56
как вариант - прогнать код через статический анализатор кода(pvs или clang).
cppcheck использовал
Поругался только на отсутствие explicit


Название: Re: Отлов ошибки
Отправлено: __Heaven__ от Август 01, 2018, 16:00
Потоки используются?

Легально ли в потоках пользоваться методами временных объектов вроде такого:

Код
C++ (Qt)
const auto &val = var->getString().trimed(); // return by value


Название: Re: Отлов ошибки
Отправлено: ViTech от Август 01, 2018, 16:20
Легально ли в потоках пользоваться методами временных объектов вроде такого:
Код
C++ (Qt)
const auto &val = var->getString().trimed(); // return by value

Можно, но осторожно :). С этой val что потом делают? Передают в другие методы, особенно, если они в других потоках могут выполняться? Особенно, если они к этому, по const QString & параметр получают.


Название: Re: Отлов ошибки
Отправлено: __Heaven__ от Август 01, 2018, 16:25
Все подобные переменные имеют время жизни в пределах итерации for и формируются из неизменяемых в процессе работы цикла объектов.


Название: Re: Отлов ошибки
Отправлено: ViTech от Август 01, 2018, 16:36
Судя по этому:
Текущего лога недостаточно. При подробном логгировании не воспроизводится
похоже, что какой-то объект таки не доживает до момента, когда им перестают пользоваться, и после его смерти пользуются его останками :). Либо race condition. ThreadSanitizer не пробовали?


Название: Re: Отлов ошибки
Отправлено: __Heaven__ от Август 01, 2018, 18:25
ThreadSanitizer не пробовали?
Нет. Не знал о таком. Спасибо, попробую.


Название: Re: Отлов ошибки
Отправлено: RedDog от Август 01, 2018, 19:26
Как только добавляю больше логов, чтобы локализовать проблему на проблемной машине, как она сразу пропадает.
Быть может кто-нибудь подкинет идей что можно ещё попробовать сделать для решения проблемы...
При подобном поведении делал свой логер, который работал в отдельном треде и не мешал (не синхронизировал) основную логику.
Не все и сразу писал, т.к к нему много кто обращался, но не мешал никому.


Название: Re: Отлов ошибки
Отправлено: __Heaven__ от Август 01, 2018, 22:53
Да, в логгере имеется мьютекс, видать, он влиял на результат
Я забыл упомянуть, у меня ещё парсинг (открытие файла) происходит в std::async, но к моменту расчёта парсинг окончен.
ThreadSanitizer показал много мест... Ругнулся также на ui->setup(this). Также ругнулся и на интересующее место.
У меня проблема интерпретации вывода, прошу помочь

Код
C++ (Qt)
   FaceSet result; // using FaceSet = QSet<Face>;
 
   const VolumeNumberList &volumeNumbers = mesh()->volumeNumbers(); // byval QVector
 
   PARALLEL_FOR
   for (int i = 0; i < volumeNumbers.count(); ++i){
       //taking volume byref
       const MeshVolume &volume = mesh()->volume(volumeNumbers.at(i)); // Read of size 2 at 0x7b080008b95c by thread T13:
 
       const auto &volumeRange = volume.range(); // can modify mutable range_
       if (!isVolumeHasToBeChecked(volume, filter) ||
               !hasIntersection(line, volumeRange)){
           continue;
       }
       const auto &shell = volume.shell(); //by value
       const auto &shellFaces = shell.shellFaces(); //by value QVector
       const FaceSet &volumeResult = intersectedFacesWithLine(line, shellFaces); // byval QSet
 
       SCALAR{
           result += volumeResult;
       }
   }
 
   return result;
 
Код
C++ (Qt)
#ifdef _OPENMP
#define PARALLEL_FOR _Pragma("omp parallel for")
#define SCALAR _Pragma("omp critical")
#else
#define PARALLEL_FOR
#define SCALAR
#endif
 


Название: Re: Отлов ошибки
Отправлено: Igors от Август 02, 2018, 05:15
Сначала отключить оmp (там ли собака порылась). Потом изучать intersectedFacesWithLine где, как я понял, и происходит расчет. Лог: не сразу печатать, в параллельном цикле слить в контейнеры (для каждой нитки свой), а по окончании уже в консоль/файл

"Race condition" - возможно переменная одновременно читается/пишется, что может быть не атомарно и повести к ошибке. Ну это всего лишь догадки


Название: Re: Отлов ошибки
Отправлено: __Heaven__ от Август 03, 2018, 15:45
Вроде, удалось подавить вывод data race санитайзера таким путём:
Указал уровень оптимизаций 0. Таким образом получил более конкретное место. Там производилось 3 обращения подряд к std::map::at заменил их на константные варианты.
Не понимаю, как константность методов влияет.
Псевдокод проблемного места
Код
C++ (Qt)
PARALLEL_FOR
for (i in range) {
   const Triangle triangle(vertices_, i);
   .....
}
 
Triangle::Triangle(vertex_map *vertices, int i)
   : a(vertices.at(i)), b(vertices.at(i+1)), c(vertices.at(i+2))
{}
 


Название: Re: Отлов ошибки
Отправлено: RedDog от Август 03, 2018, 21:42
vertices.at(...) потокобезопасны?


Название: Re: Отлов ошибки
Отправлено: Igors от Август 04, 2018, 12:54
Псевдокод проблемного места
Код
C++ (Qt)
PARALLEL_FOR
for (i in range) {
   const Triangle triangle(vertices_, i);
   .....
}
 
Triangle::Triangle(vertex_map *vertices, int i)
   : a(vertices.at(i)), b(vertices.at(i+1)), c(vertices.at(i+2))
{}
 
Неудачный псевдокод, здесь важно является ли for первым циклом (будет ли omp сама заниматься переменной "i"), тогда напр пройти с шагом 3 нельзя. И не видно что заменено на константные методы (vertex_map не const, значит будет вызываться неконстантный at). К слову: если at выбросит исключение - оно поймается в одной из ниток omp (необязательно главной).

А вообще конечно вряд ли "то место". Если бы что не так с at  - там было бы "костей не собрать", не то что редкий вылет.


Название: Re: Отлов ошибки
Отправлено: __Heaven__ от Август 05, 2018, 14:54
vertices.at(...) потокобезопасны?

Не знаю. Потокобезопасен ли неконстантный std::map::at?


Название: Re: Отлов ошибки
Отправлено: __Heaven__ от Август 05, 2018, 14:56
Исключения в at бросаться не должны - все запрашиваемые элементы существуют


Название: Re: Отлов ошибки
Отправлено: Igors от Август 06, 2018, 03:50
Не знаю. Потокобезопасен ли неконстантный std::map::at?
Ну если "все эл-ты существуют" - то скорее всего да (а по-хорошему в доке указывается "thread-safe").  Но чего Вы уперлись в это место? Какой-то санитар на него указал? Так верить ему необязательно. Ищите запись, ошибка обязательно связана с ней