2 / 2 / 0
Регистрация: 07.04.2016
Сообщений: 248
1

wxWidgets + многопоточность = ошибка сегментирования

08.08.2023, 08:16. Показов 2855. Ответов 6
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте.

Имеем:
1. wxWidgets 3.2.2;
2. windows 10 x64;
3. debian 11.5 (virtualBox);
4. многопоточность (std );
5. socket tcp\ip.

Что не так:
1. В виндовс работает на линуксе нет;
2. В линуксе при запуске через терминал выдает ошибку "ошибка сегментирования"

Описание:
Что делал см. ниже.
Кликните здесь для просмотра всего текста

Изначально прогу писал на винде, все запускалось, потом этот же код перенес на линукс и при запуске стал получать ошибки, некоторые устранил, но одну(если она одна) устранить на данный момент не понимаю как. Дело касается многопоточности.
В программе использую потоки из пространства имен std а не виджетовский класс. Прочитав мануал, было сказано делать многопоточность так, что бы графику обновлял\занимался основной поток. Как мне кажется(хотя есть вопросы). я так и сделал.
Запускаю прогу через терминал и вижу сообщение об ошибке сегментирования, убил весь вечер пересматривая циклы с массивами и векторами. Вполне возможно пропустил. Но вроде все ок.


Что делал:
1. Весь вечер пересматривал циклы с массивами и векторами. Вроде все ок;
2. В конструкторе в самом конце создал цикл, в котором создаются события нажатия на кнопку "присоединиться", далее после обработки этого события вызывается метод, в котором создается соединение, включаются\отключаются кнопки и устанавливается текст:
Говнокод этого метода:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
void Class::makeConnection (int aI) {
 
    m_darrayDisconnectButton [aI] ->Enable (true);
 
    this->changeStatusConnect (aI);
 
    #ifdef windows1
        SOCKET socket1 = socket (AF_INET, SOCK_STREAM, 0);
        m_arraySocket [aI] = socket1;
    #endif // windows1
 
    #ifdef linux1
        int socket1 = socket (AF_INET, SOCK_STREAM, 0);
        m_arraySocket [aI] = socket1;
    #endif // linux1
 
    std::string stringIp = (m_darrayTextCtrlIp [aI] ->GetLineText (0)).ToStdString();
    std::string stringPort = (m_darrayTextCtrlPort [aI] ->GetLineText(0)).ToStdString();
 
    sockaddr_in addr1;
    addr1.sin_family = AF_INET;
    addr1.sin_addr.s_addr = inet_addr (stringIp.c_str());
    int intPort = stoi (stringPort);
    addr1.sin_port = htons (intPort);
 
    wxString wxStringResult (wxEmptyString);
    wxString wxStringResultPart1 (wxT ("111"));
    int attempt = 1;
    int codeCheck = 0;
 
    while (attempt < 4) {
        wxString wxStringAttempt = wxString::Format (wxT ("%i"), attempt);
        wxString wxStringResultPart2 (wxT ("/3"));
        wxStringResult = wxStringResultPart1 + wxStringAttempt
                                    + wxStringResultPart2;
 
        m_darrayStatTextInfoBook2 [aI] ->SetLabel (wxStringResult);
        wxStringResult.clear();
        m_darrayStatTextInfoBook1 [aI] ->SetLabel (m_darrayStatTextInfoBook2 [aI] ->GetLabelText() );
 
        codeCheck = connect (m_arraySocket [aI], (sockaddr*)&addr1, sizeof (addr1));
 
        ++attempt;
 
        if (codeCheck == 0) {
            break;
        }
 
        if ( ! m_darrayDisconnectButton [aI] ->IsEnabled()) {
            codeCheck == -1;
            break;
        }
    } // while (attempt).
 
    if (codeCheck != 0) {
        #ifdef windows1
            closesocket (m_arraySocket [aI]);
        #endif // windows1
 
        #ifdef linux1
            close (m_arraySocket [aI]);
        #endif // linux1
 
        this->markTime (wxT ("111"), aI);
        m_matrixInstructionLog [aI] [m_arrayIndexInstructionLog [aI] ] = 1;
        ++m_arrayIndexInstructionLog [aI];
 
        m_darrayStatTextInfoBook2 [aI] ->SetLabel (wxT ("111"));
        m_darrayStatTextInfoBook1 [aI] ->SetLabel (m_darrayStatTextInfoBook2 [aI] ->GetLabelText() );
        m_darrayConnectButton [aI] ->Enable (true);
        m_darrayDisconnectButton [aI] ->Enable (false);
 
        if (m_numberOfConnection == 0) {
            m_disconnectAllButton ->Enable (false);
            m_connectAllButton->Enable (true);
        }
        else if ( (m_numberOfConnection > 0)
                    | (m_numberOfConnection < m_numberOfMoxa) ) {
            m_disconnectAllButton ->Enable (true);
            m_connectAllButton->Enable (true);
        }
        else if (m_numberOfConnection == m_numberOfMoxa) {
            m_disconnectAllButton ->Enable (true);
            m_connectAllButton->Enable (false);
        }
    }
    else if (codeCheck == 0) {
        m_arraySendingError [aI] = false;
        m_arrayReceived [aI] = false;
        m_arrayReconnect [aI] = false;
 
        m_mutex1.lock();
            ++m_numberOfConnection;
        m_mutex1.unlock();
 
        m_arrayStatusStop [aI] = true;
        m_arrayStatusPause [aI] = false;
 
        if (m_darrayCheckBoxGeneralParameters [aI] ->IsChecked() ) {
            this->copyGenerallSettings (aI);
        }
 
        wxString wxStringPart1 (wxT ("111"));
        this->markTime ( (*m_darrayNameEquipments [aI] + wxStringPart1), aI);
        m_matrixInstructionLog [aI] [m_arrayIndexInstructionLog [aI] ] = 1;
        ++m_arrayIndexInstructionLog [aI];
 
        this->switchOnAcDc (aI);
        this->markTime (wxT ("111"), aI);
        m_matrixInstructionLog [aI] [m_arrayIndexInstructionLog [aI] ] = 1;
        ++m_arrayIndexInstructionLog [aI];
        m_darrayStatTextInfoBook2 [aI] ->SetLabel (wxT ("111"));
        m_darrayStatTextInfoBook1 [aI] ->SetLabel (m_darrayStatTextInfoBook2 [aI] ->GetLabelText() );
        m_Graph->setColorGraph (aI, *m_darrayWxColor
                                                        [
                                    m_darrayChoiceColour [aI] ->GetSelection ()
                                                        ]);
 
        std::thread t1 (&Ses21::sendPackage, this, aI);
        t1.detach ();
 
        m_Graph->setCurrentGraph (aI);
 
        wxCommandEvent event1 (wxEVT_RADIOBUTTON,
                                        (m_darrayRadioButton [6])->GetId() );
        event1.SetEventObject (this);
        ProcessWindowEvent (event1);
 
        this->markTime (wxT ("111"), aI);
        m_matrixInstructionLog [aI] [m_arrayIndexInstructionLog [aI] ] = 1;
        ++m_arrayIndexInstructionLog [aI];
        m_darrayStatTextInfoBook2 [aI] ->SetLabel (wxT ("111"));
        m_darrayStatTextInfoBook1 [aI] ->SetLabel (m_darrayStatTextInfoBook2 [aI] ->GetLabelText() );
 
        this->markSettings (aI);
 
        this->enableParameters (true);
        this->enableParameters (true, aI);
 
        wxCommandEvent event2 (wxEVT_CHECKBOX,
                                    (m_darrayCheckBoxGeneralParameters [aI])->GetId() );
        event2.SetEventObject (this);
        ProcessWindowEvent (event2);
 
        this->enableButtons (m_buttonChange->GetId(), true);
        this->enableButtons (m_buttonStop->GetId(), true);
        this->enableButtons (m_buttonPause->GetId(), true);
        this->enableButtons (m_buttonStart->GetId(), true);
 
        this->enableButtons ( (m_darrayPingButton [aI])->GetId(), true);
        this->enableButtons ( (m_darrayStartButton [aI])->GetId(), true);
        this->enableButtons ( (m_darrayChangeButton [aI])->GetId(), true);
        this->enableButtons ( (m_darrayStopButton [aI])->GetId(), true);
        this->enableButtons ( (m_darrayPauseButton [aI])->GetId(), true);
        this->enableButtons ( (m_darrayDisconnectButton [aI])->GetId(), true);
        this->enableButtons ( (m_darrayConnectButton [aI])->GetId(), false);
 
        this->enableButtons (m_disconnectAllButton->GetId(), true);
        }
    }
}
3. Если закомментировать все строки у "else if (codeCheck == 0)" то прога запускается;
4. Если раскомментировать в "else if (codeCheck == 0)" 3 строки, в которых происходит установка значений в массиве, а остальные не раскомментировать, то прога стабильно не запускается и пишет "ошибка сегментирования". Видимо я неправильно понял как использовать многопоточность...

Вопросы:
1. Где я допустил ошибку(а если она в этом методе, то и в других) ?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
08.08.2023, 08:16
Ответы с готовыми решениями:

wxWidgets: 2 х wxTextCtrl = ошибка завершения программы
Здравствуйте. Имеем: Простой код с двумя объектами wxTextCtrl. Что не работает: При...

Странная ошибка компиляции проекта Code::Blocks, wxWidgets
Здравствуйте. Встретился с багом, над выявлением которого работал опытным путём весь день. ...

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

Ошибка в коде (Ошибка сегментирования (core dumped)
Добрый день. Подскажите пожалуйста, где ошибка в коде? char ch; string s; ...

Ошибка сегментирования
Добрый день, возникла проблема: Вот программа, суть из исходного файла у слов удаляется окончание...

6
18838 / 9839 / 2406
Регистрация: 30.01.2014
Сообщений: 17,277
12.08.2023, 12:03 2
Лучший ответ Сообщение было отмечено Palich как решение

Решение

Palich, с многопоточностью (если конечно действительно в ней дело, а то не факт) чтобы найти ошибку нужно видеть весь контекст использования разделяемых ресурсов, а его вы не предоставили. Вот почему, например, нет метода sendPackage? Он ведь явно что-то делает с данными, которые вы подготовили в проблемной ветке условия.

В этом коде я пока вижу только ошибку дизайна. У вас и GUI и низкоуровневая работа с сетью и какая-то логика - все в одном методе. Это очень плохо и поэтому вам так сложно программировать и находить ошибки.
По-хорошему работа с сетью - это должен быть отдельный класс, который вы отдельно оттестируете, определите для него публичные контракты и в соответствии с ними будете его использовать в какой-то логике. Сама же логика должна быть отделена от GUI: сможете написать так, чтобы вашу логику можно было в другую GUI-подсистему сунуть, считайте что цель достигнута. А все это к чему? К простоте. Чем меньше зависимостей между компонентами программы, тем проще их тестировать и исправлять в них ошибки.
0
204 / 139 / 23
Регистрация: 26.11.2022
Сообщений: 622
13.08.2023, 19:45 3
Цитата Сообщение от Palich Посмотреть сообщение
В линуксе при запуске через терминал выдает ошибку "ошибка сегментирования"
что мешает запустить в отладчике в линуксе? и посмотреть где беда
0
2 / 2 / 0
Регистрация: 07.04.2016
Сообщений: 248
23.08.2023, 10:04  [ТС] 4
спасибо за ответы, пока не могу вернуться к этой проблеме. Как вернусь, напишу что сделал и что получилось.
0
2 / 2 / 0
Регистрация: 07.04.2016
Сообщений: 248
21.09.2023, 23:37  [ТС] 5
Цитата Сообщение от DrOffset Посмотреть сообщение
В этом коде я пока вижу только ошибку дизайна.
о да, я бы сказал, вся прога сплошная ошибка )

Цитата Сообщение от DrOffset Посмотреть сообщение
По-хорошему работа с сетью - это должен быть отдельный класс, который вы отдельно оттестируете
Потрясающее раскрытие мне глаз ) На тот момент, мне казалось это через чур: создавать целый класс для 2х методов передачи-приема пакетов.

Цитата Сообщение от DrOffset Посмотреть сообщение
Сама же логика должна быть отделена от GUI:
А вот тут у меня идет некоторое недопонимание: взятие текста из текстового окна "wxTextCtrlIp"
Цитата Сообщение от Palich Посмотреть сообщение
std::string stringIp = (m_darrayTextCtrlIp [aI] ->GetLineText (0)).ToStdString();
должно быть отделено ? т.е. нельзя неосновным потоком выполнять этот код ?

Цитата Сообщение от DrOffset Посмотреть сообщение
чтобы вашу логику можно было в другую GUI-подсистему сунуть, считайте что цель достигнута.
Сделал, впихнул. Есть отдельный класс, в этом классе нет ничего, что связано с графической библиотекой. Правда, пришлось нагородить\усложнить собственными событиями для сигнализации основному потоку обработать результат работы с сетью.

Цитата Сообщение от DrOffset Посмотреть сообщение
А все это к чему? К простоте.
Начинается у меня просто, заканчивается говнокодом



В общем сделал, все запускается, работает.
Пока делал, нашел пару ошибок, о которых бы и не вспомнил.

Добавлено через 3 минуты
Цитата Сообщение от Aledveu Посмотреть сообщение
что мешает запустить в отладчике в линуксе? и посмотреть где беда
отладчик сильно помогает мне в неграфических программах, а вот с графической у меня недопонимания, возможно, нужно как-то настроить его, суть в том что он указывает место ошибки не в моих файлах, а в библиотечных, причем как он туда попал, после какой последовательности отработанных моих строчек кода, не ясно. Эм.... надеюсь, я донес мысль ) Писал, имел в виду отладчик, который в ide.
0
18838 / 9839 / 2406
Регистрация: 30.01.2014
Сообщений: 17,277
22.09.2023, 12:21 6
Цитата Сообщение от Palich Посмотреть сообщение
т.е. нельзя неосновным потоком выполнять этот код ?
Нельзя. Об этом в документации прямым текстом сказано:
When writing a multi-threaded application, it is strongly recommended that no secondary threads call GUI functions. The design which uses one GUI thread and several worker threads which communicate with the main one using events is much more robust and will undoubtedly save you countless problems (example: under Win32 a thread can only access GDI objects such as pens, brushes, device contexts created by itself and not by the other threads).
https://docs.wxwidgets.org/3.0... hread.html

Но я даже не об этом говорил, а о том, что у вас в принципе и логика, и сеть и GUI перемешаны в одном методе. Естественно точки заимодействия логики с GUI все равно останутся, но в идеале это взаимодействие должно быть локализовано, а не происходить в рандомных частях выполнения логики.

Цитата Сообщение от Palich Посмотреть сообщение
как он туда попал, после какой последовательности отработанных моих строчек кода, не ясно
Backtrace не помогает об этом узнать? Пример "неясности" можете привести?

Цитата Сообщение от Palich Посмотреть сообщение
Начинается у меня просто, заканчивается говнокодом
Кто бы что не говорил, но в программировании нужно не только самостоятельно писать, но и читать (книжки и чужой код), иначе никакого прогресса не будет.
0
2 / 2 / 0
Регистрация: 07.04.2016
Сообщений: 248
22.09.2023, 14:22  [ТС] 7
Цитата Сообщение от DrOffset Посмотреть сообщение
Backtrace не помогает об этом узнать? Пример "неясности" можете привести?
пойду читать что это такое.
0
22.09.2023, 14:22
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
22.09.2023, 14:22
Помогаю со студенческими работами здесь

ошибка сегментирования
При запуске скомпилированной (gcc) программы выскакивает ошибка сегментирования, а при запуске ее...

Ошибка сегментирования
Здравствуйте! Подскажите, пожалуйста, почему программа выводит &quot;Ошибка сегментирования&quot;. #include...

Ошибка сегментирования.
Всем доброго времени суток! Помогите пожалуйста разобраться в чем дело, пишу программу( суть найти...

Ошибка сегментирования
Всем привет. Ситуация такая: У меня есть g++ версии &quot;gcc version 6.3.0 20170516 (Debian...

Ошибка сегментирования
Здравствуйте. Здесь представлена программа, единственное назначение которой промоделировать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru