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

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

Страниц: 1 [2]   Вниз
  Печать  
Автор Тема: Ошибка "Segmentation fault"  (Прочитано 3310 раз)
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #15 : Апрель 04, 2024, 13:50 »

Одна нормальная тема в год - и ту закрывает  Плачущий
Не вопрос, отменил)) Надо бы тогда тему как-то уточнить, чтобы обсуждение пошло в нужном русле.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #16 : Апрель 04, 2024, 15:23 »

Крах программы наблюдается, когда я перед загрузкой новой конфигурации удаляю старые объекты контроллеров, использующих протоколы modbus rtu по протоколу TCP/IP. Это мой компонент (QModbusRtuClient), я сделал его на основе уже имеющихся в составе qtserialbus, исходники я публиковал где-то здесь. Ключевые фрагменты кода (не существенные части я пропускаю, отмечено '...'):

Код
C++ (Qt)
CModbusInterface::CModbusInterface(...) {
...
       //
       modbusDevice = new QModbusRtuClient(this);
...
}
 
CModbusInterface::~CModbusInterface(){
   if (modbusDevice) {
       modbusDevice->deleteLater();
   }
}
 

Фрагмент кода не должен приводить к краху по рассматриваемой причине.
Код в деструкторе лишний, так как при конструировании modbusDevice указан родитель this, который и управляет его временем жизни.

после чего сокетом формируется сигнал ошибки и отправляется уже удаленному modbusDevice. И программа валится.

Все сигнал слот соединения разрываются и все сообщения для modbusDevice удаляются из очереди обработки при его удалении.
Поэтому ситуации "сокетом формируется сигнал ошибки и отправляется уже удаленному modbusDevice" при корректной реализации быть не может.

Здесь на лицо проблема конкурентного доступа к экземпляру объекта. Обработка сообщений происходит в одном потоке, удаление объекта в другом.
Можно проверить это с помощью определения своего типа производного QModbusRtuClient, например, и вывода и сравнении информации о потоке в деструкторе и обработчиках сигналов.

Вариантов управления временем жизни не так уж и много:

  • объект на стеке - удалиться при потере области видимости в том же потоке, где был создан, независимо от потока обработки событий
  • член класса - удалиться вместе с экземпляром агрегата, независимо от потока обработки событий
  • умный указатель - удалиться вместе удаления умного указателя, независимо от потока обработки событий
  • Qt parent-child отношение - удалиться вместе с экземпляром родителя, независимо от потока обработки событий
  • new/delete - удалиться в вместе вызова delete, независимо от потока обработки событий
  • deleteLater - удалиться в потока обработки событий, независимо от других способов владения (кроме Qt parent-chaild)


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

Удаление, изменение и т.д. конфигурации не должно приводить в краху программы. Решение задачу с помощью "отложенное удаление старой конфигурации ...", лишь усугубит ситуацию, так как проблема никуда не денется, а частота её появления уменьшиться.



Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #17 : Апрель 04, 2024, 17:00 »

Здесь на лицо проблема конкурентного доступа к экземпляру объекта. Обработка сообщений происходит в одном потоке, удаление объекта в другом.
Можно проверить это с помощью определения своего типа производного QModbusRtuClient, например, и вывода и сравнении информации о потоке в деструкторе и обработчиках сигналов.
Только не это. Обработка сообщений и удаление объектов осуществляется в одном потоке - в потоке ядра. Собственно, ядро владеет конфигурацией, его задача - обеспечение асинхронного взаимодействия с периферийным железом.
Запуск обновления конфигурации осуществляется из другого, клиентского потока, в котором живет веб-интерфейс. взаимодействие клиентских потоков с ядром - через сигнал/слотовый механизм. Я использую для этого специальный класс (потоковый адаптер).

По остальным замечаниям - позже, когда освобожусь немного.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Igor_S
Новичок

Offline Offline

Сообщений: 9


Просмотр профиля
« Ответ #18 : Апрель 05, 2024, 10:55 »

Маловато "фактов". Хорошо бы получить останов (или хотя бы краш) в своем коде/фильтре. Посмотреть что за QEvent, здесь вариантов немного. Убедиться что это действительно удаление, печатая в ~QModbusRtuClient адрес экземпляра
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #19 : Апрель 05, 2024, 19:54 »

Как же я смогу это сделать, если ~QModbusRtuClient уже исполнился, а краш происходит через несколько секунд? Проблема-то в том и состоит, что процессы, приводящие к аварийному завершению, связаны (ну, я так думаю;)) с сокетом, а приемник уже уничтожен.
Прямо вот сейчас пришла мысль - можно было бы создать отладочный объект-приемник, который живет все время работы программы, и подключить его к возможным источникам сигналов. Но поздно - я уже все переделываю, не хочется возвращаться к проблеме, которая имеет чисто академический интерес))
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Igor_S
Новичок

Offline Offline

Сообщений: 9


Просмотр профиля
« Ответ #20 : Апрель 06, 2024, 13:37 »

Как же я смогу это сделать, если ~QModbusRtuClient уже исполнился, а краш происходит через несколько секунд?
напр так
Код:
QModbusRtuClient::~QModbusRtuClient( void )
{
 printf("~QModbusRtuClient %p\n", this);
}
И при краше сравнить receiver c напечатанным.
Но поздно - я уже все переделываю, не хочется возвращаться к проблеме, которая имеет чисто академический интерес))
Хорошо если так  Улыбающийся
Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #21 : Апрель 09, 2024, 16:13 »

И при краше сравнить receiver c напечатанным.
Как-то не сразу до меня дошло, что адрес receiver можно взять из стека)) Ну ладно, пригодится на будущее, спасибо.
Хорошо бы где-нибудь почитать про методы отладки в Qt - наработанные приемы, инструменты. Может, есть монография по этой теме?
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Igor_S
Новичок

Offline Offline

Сообщений: 9


Просмотр профиля
« Ответ #22 : Апрель 09, 2024, 16:52 »

Хорошо бы где-нибудь почитать про методы отладки в Qt - наработанные приемы, инструменты. Может, есть монография по этой теме?
О монографии не слышал. Кстати надо печатать и в конструкторе, возможна ABA. Вообще первое что нужно сделать - добиться стабильности краша, идеи/мысли для этого у Вас есть. Если стабильно летит - дальше уже "дело техники" и все такое. Самое мерзкое если появится так раз в месяц - и с приветом, вымотает все кишки  Плачущий
Записан
Страниц: 1 [2]   Вверх
  Печать  
 
Перейти в:  


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