Просмотр сообщений
|
Страниц: [1] 2 3 ... 39
|
1
|
Qt / Многопоточное программирование, процессы / Re: Ошибка "Segmentation fault"
|
: Апрель 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)
Основное, вроде, перечислил. Почти любая суперпозиция способов владения - крах программы с похожей проблемой, как здесь. Удаление, изменение и т.д. конфигурации не должно приводить в краху программы. Решение задачу с помощью "отложенное удаление старой конфигурации ...", лишь усугубит ситуацию, так как проблема никуда не денется, а частота её появления уменьшиться.
|
|
|
2
|
Qt / Многопоточное программирование, процессы / Re: Ошибка "Segmentation fault"
|
: Апрель 04, 2024, 08:21
|
C++ (Qt) QObject::connect(&archivingThread, &QThread::finished, archiving, &CServiceArchives::deleteLater);
If deleteLater() is called after the main event loop has stopped, the object will not be deleted. Что-то подсказывает мне, что archiving никогда не удалиться), цикл обработки событий уже не работает. Одна морока с этим moveToThread Конечно, хотелось бы увидеть весь проект или тестовый пример, или хотя бы стек вызовов по всем потокам.
|
|
|
4
|
Qt / Многопоточное программирование, процессы / Re: Ошибка "Segmentation fault"
|
: Апрель 03, 2024, 14:56
|
Или может сигнал слот взаимодействие через обычный AutoConnection, а потом используется moveToThread()?
А это имеет значение? Если да, то позор мне... Такие ошибки чаще всего связаны именно с этим. Значение имеет огромное. Когда осуществляется connect по AutoConnection выбирается способ соединения в соответствии с потоками обработки событий объектов. Если потоки одинаковые, то AutoConnection == DirectConnection. После moveToThread объект меняет поток обработки событий, а соединения остаются связанными через DirectConnection. События в одном потоке, сигнал слот в другом, отсюда следует UB в случае конкурентного доступа к полям экземпляра объекта. И программа может упасть не обязательно из-за деструктора, а в любой момент в процессе работы. А уж если деструктор вызвался, то практически гарантировано упадет (но есть случаи, когда может и не упасть)). UB оно такое).
|
|
|
5
|
Qt / Многопоточное программирование, процессы / Re: Ошибка "Segmentation fault"
|
: Апрель 01, 2024, 08:37
|
Такое впечатление, что receiver не живой или почти не живой. Базовый тип QObject выглядит подозрительно.
Нет ли сигнал слот взаимодействия через DirectConnection для объектов, связанных с разными потоками? Или может сигнал слот взаимодействие через обычный AutoConnection, а потом используется moveToThread()?
|
|
|
8
|
Qt / Работа с сетью / Re: tcp proxy server. Только на berkley sockets (select/poll/epoll)
|
: Январь 31, 2024, 10:58
|
При подключении нового клиента, выполняем подключение к серверу и после этого имеем пару сокетов client-proxy и proxy-server, вот все что приходит по первому сокету, нужно отправить во второй и наоборот. Если один из сокетов закрывается, то нужно закрыть и второй. Как правило эти два сокета хранятся в объектах, которые называют session. Я тоже к такой схеме пришёл). Назвал объект только proxy_client. Как мне узнать, что ответ получен не полностью и ожидается продолжение?
Нужно реальный трафик смотреть. В общем случае никак. Если в сети текст, то надеяться, что есть разделитель ";", либо по слову "SELECT" или другим косвенным признакам. Если бинарный протокол, то его нужно знать, скорее всего, где-то длина пакета должна быть.
|
|
|
9
|
Qt / Работа с сетью / Re: tcp proxy server. Только на berkley sockets (select/poll/epoll)
|
: Январь 30, 2024, 17:04
|
С сетью работал оочень давно). Похоже, что должно работать. Необходимо распарсить сетевые пакеты, проходящие через прокси, в которых содержатся SQL запросы, извлечь эти запросы из пакетов и записать их в файл в виде текста (по одному запросу в строке, структура неважна) Вот этой части не нашел. В обработчике только вывод в cout. По идее SQL запросы необходимо собирать из сетевых пакетов. При этом пакеты могут неожиданно разрываться и слипаться между собой. Должен быть какой-то признак окончания запроса (м.б. символ";").
|
|
|
10
|
Разное / Говорилка / Re: Регистрация программы в Росреестре
|
: Январь 19, 2024, 09:50
|
Коллеги, прошло много времени, появиличь ли прецеденты регистрации программ на Qt в росреестре?
Да, мы регистрировали несколько продуктов в 2021-2023. По моему, мы нанимали консалтинговую фирму для подготовки документов.
|
|
|
11
|
Qt / Вопросы новичков / Re: как правильно работать с Qt, чтобы не было утечек памяти?
|
: Декабрь 11, 2023, 16:24
|
Проблема владения не редкий вопрос на форуме), например, Про деревянный айтем )). Паттерн parent-child, как раз про отношение часть-целое, отношение владения. В архитектуре QObject владение child, вроде как, передается parent, а вроде как и нет. Никто не мешает удалить child напрямую, минуя parent. Такое вот двойное управление ресурсами. Как следствие вопросы типа должен ли я озаботится о зачистке памяти?, так как интуитивно не понятно, в каком случае Qt почистит ресурсы, а в каком нет. Постоянно нужно в доки глядеть). Но я уверен, что >90% разработчиков этот вопрос никак не волнует и интерпретируется даже, как удобство). Слышал как-то это обходится "муванием". И как тогда удалять тот же виджет (чайлд)? Можно и с move и без него. Удалять виджет следовало бы либо с помощью API владельца (parent), либо сначала извлечь child из parent, а затем удалять. Здесь расписан пример реализации иерархии tree-example. Отношение parent-child реализована для класса Node.
|
|
|
12
|
Qt / Вопросы новичков / Re: как правильно работать с Qt, чтобы не было утечек памяти?
|
: Декабрь 06, 2023, 10:34
|
Да уж наворотили в Qt всего . Архитектура Qt закладывалась во времена без unique_ptr, shared_ptr и move семантики. Но вопросы владения ресурсами и механизм RAII никто не отменял. Как разработчик будет управлять ресурсами - это его дело. Можно new/delete использовать и сырые указатели (типа классические), но это трудоемко в плане подчистки ресурсов. Как минимум нужно в деструкторе удалить, а желательно ещё учесть возможность обработки исключений. Умные указатели unique_ptr, shared_ptr и другие решают задачу подчистки ресурсов, с ними проще. Разработчики Qt в своей архитектуре смешали вопрос иерархии экземпляров объектов и вопрос владения, заложив правило, что верхний в иерархии объект удаляет объекты ниже в иерархии. Это привело к тому, что в Qt традиционно используют сырые указатели. Тем не менее, сами разработчики Qt рекомендуют использовать unique_ptr для управления ресурсами (стандартный почти аналог QScopedPointer). При использовании сырых указателей классической ошибкой новичков является не указание родителя у экземпляра объекта (чаще всего this) C++ (Qt) QObject * obj = new QObject; // должно быть QObject( this )
В этом случае никто не владеет объектом, куда указывает obj => потенциальные утечки ресурсов памяти. В случае с умным указателем C++ (Qt) unique_ptr< QObject > obj = make_unique< QObject >();
ресурсом владеет умный указатель, который в любом случае удалит объект, на который указывает obj.
|
|
|
13
|
Qt / Вопросы новичков / Re: Работа с ком-портом в Qt
|
: Ноябрь 09, 2023, 14:55
|
Здесь имеется несоответствие входящих параметров метода write, который принимает const char * или QByteArray, и результата метода text, который возвращает QString. Нужно явное преобразование QString в QByteArray (сериализация), например в байты формата utf8. C++ (Qt) serialPort.write(this->ui->txtInput->text().toUtf8() );
При приеме байт необходимо делать обратное преобразование из байт в текст (десериализацию) с помощью метода QString::fromUtf8.
|
|
|
15
|
Qt / Общие вопросы / Re: помогите пожалуйста разобраться с ошибками(клас наследованый от QPainter)
|
: Август 22, 2023, 15:47
|
Если закрыть глаза на попытку смешать теплое и зеленое, то должно быть так C++ (Qt) class Square : public QObject // всегда первый , public QPainter { Q_OBJECT public: Square(QObject* parent = nullptr); void drawSquare(QPoint point,QPoint point2,QPoint point3,QPoint point4); };
Но , не нужно смешивать средство рисования QPainter и объект с поведением. QPainter всегда можно создать на лету с указанием устройства, на котором требуется рисовать.
|
|
|
|
|