Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/13: Рейтинг темы: голосов - 13, средняя оценка - 5.00
2 / 2 / 0
Регистрация: 27.11.2016
Сообщений: 62
1

Ошибка при попытке вызвать join() у потоков

24.12.2019, 11:13. Показов 2551. Ответов 7

Здравствуйте, уважаемые форумчане! Столкнулся с проблемой: при попытке присоединить потоки с помощью join() вызывается исключение в операторе delete, а именно void __CRTDECL operator delete(void* const block) noexcept, привожу скриншот.

Сама программа выглядит примерно следующим образом:

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
#include <thread>
#include <vector>
 
class MyClass1
{
private:
 struct SomeStruct1
 {};
 SomeStruct1* Arr;
public:
 MyClass1(const unsigned int Count)
 {
  this->Arr = new SomeStruct1[Count];
 }
 ~MyClass1()
 {
  delete[] this->Arr;
 }
}
 
class MyClass2
{
private:
 struct SomeStruct2
 {};
 SomeStruct2* Arr;
public:
 MyClass2(const unsigned int Count)
 {
  this->Arr = new SomeStruct2[Count];
 }
 ~MyClass2()
 {
  delete[] this->Arr;
 }
}
 
void Thread_Func(MyClass1 &obj1, MyClass2 obj2)
{
 //some actions
 //Функция организована так, что потоки друг другу не мешают,
 //борьбы за разделяемые ресурсы - объекты - нет
}
 
int main()
{
 MyClass1 obj1(100u);
 MyClass2 obj2(200u);
 
 std::vector<std::thread> Threads; //Вектор потоков
 unsigned int procs = std::thread::hardware_concurrency();
 for (unsigned int i = 0u; i < procs ; ++i)
 {
  Threads.emplace_back([&obj1,obj2]()
  {
   Thread_Func(obj1, obj2);
  });
 }
 
 for (auto &this_thread : Threads)
 {
  if (this_thread.joinable())
  {
    this_thread.join(); //Присоединяем потоки (синхронизируем) если возможно !!! ЗДЕСЬ ОШИБКА КАК НА СКРИНШОТЕ ! ! ! 
  }
 }
 return 0;
}
Сначала я грешил на деструкторы описанных мной классов, экземпляры которых попадают через лямбду в функцию потока, но нет, судя по срабатываниям точек останова, программа в них даже не попадает, то есть, скорее всего, дело не в классах.

В чем может быть проблема?

Благодарю за уделенное внимание.
Миниатюры
Ошибка при попытке вызвать join()  у потоков  
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.12.2019, 11:13
Ответы с готовыми решениями:

Ошибка ORA-00900 при попытке вызвать процедуру из C#
Здрасьте! Ошибка появляется когда я пытаюсь вызвать процедуру через C# (связь OleDB). Процедура:...

Ошибка 'Error privileged instruction' при попытке вызвать процедуру
При попытке вызвать процедуру другой формы из другого юнита передаваемую как параметр, получаюunit...

Ошибка при попытке вызвать редактор локальной групповой политики gpedit.msc
При попытке вызвать редактор локальной групповой политики командой gpedit.msc выскакивает это окно...

Ошибка "Элемент не существует в текущем контексте" при попытке вызвать поле объекта одного компонента в другом
Вот собственно код, главный файл и 2 компонента. Это попытка создать игру в XNA, но если верить...

7
2 / 2 / 0
Регистрация: 27.11.2016
Сообщений: 62
24.12.2019, 11:18  [ТС] 2
Еще интересный момент: решил притормозить присоединение потоков и заставить основной поток поафэкашить, пока остальные потоки работают, main изменил следующим образом:

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
int main()
{
 MyClass1 obj1(100u);
 MyClass2 obj2(200u);
 
 std::vector<std::thread> Threads; //Вектор потоков
 unsigned int procs = std::thread::hardware_concurrency();
 for (unsigned int i = 0u; i < procs ; ++i)
 {
  Threads.emplace_back([&obj1,obj2]()
  {
   Thread_Func(obj1, obj2);
  });
 }
 std::this_thread::sleep_for(std::chrono::milliseconds(1000)); //ТА ЖЕ САМАЯ ОШИБКА!!!
 for (auto &this_thread : Threads)
 {
  if (this_thread.joinable())
  {
    this_thread.join(); //Присоединяем потоки (синхронизируем) если возможно !!! ЗДЕСЬ ОШИБКА КАК НА СКРИНШОТЕ ! ! ! 
  }
 }
 return 0;
}
Скорее всего, ошибка возникает при уничтожении объекта std::chrono::milliseconds(1000), но почему, я не понимаю.
Библиотека chrono, разумеется, подключена.
0
6739 / 4537 / 1840
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
24.12.2019, 11:28 3
Цитата Сообщение от Юрий Мамонтов Посмотреть сообщение
В чем может быть проблема?
Ссылку потерял Threads.emplace_back([&obj1, &obj2]()
1
Эксперт С++
8554 / 4130 / 908
Регистрация: 15.11.2014
Сообщений: 9,326
24.12.2019, 11:29 4
Лучший ответ Сообщение было отмечено Юрий Мамонтов как решение

Решение

Цитата Сообщение от Юрий Мамонтов Посмотреть сообщение
В чем может быть проблема?
проблема не в самом джойне.

у тебя тут нарушение правила "3х":
если тебе понадобился деструктор,
значит тебе нужен конструктор копии и оператор= тоже.

отсутствие онных и приводит приводят процесс к аварии.


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


Код
Warning(s):
source_file.cpp:5:7: warning: ‘class MyClass1’ has pointer data members [-Weffc++]
 class MyClass1
       ^
source_file.cpp:5:7: warning:   but does not override ‘MyClass1(const MyClass1&)’ [-Weffc++]
source_file.cpp:5:7: warning:   or ‘operator=(const MyClass1&)’ [-Weffc++]
source_file.cpp: In constructor ‘MyClass1::MyClass1(unsigned int)’:
source_file.cpp:12:2: warning: ‘MyClass1::Arr’ should be initialized in the member initialization list [-Weffc++]
  MyClass1(const unsigned int Count)
  ^
source_file.cpp: At global scope:
source_file.cpp:22:7: warning: ‘class MyClass2’ has pointer data members [-Weffc++]
 class MyClass2
       ^
source_file.cpp:22:7: warning:   but does not override ‘MyClass2(const MyClass2&)’ [-Weffc++]
source_file.cpp:22:7: warning:   or ‘operator=(const MyClass2&)’ [-Weffc++]
source_file.cpp: In constructor ‘MyClass2::MyClass2(unsigned int)’:
source_file.cpp:29:2: warning: ‘MyClass2::Arr’ should be initialized in the member initialization list [-Weffc++]
  MyClass2(const unsigned int Count)
  ^
source_file.cpp: At global scope:
source_file.cpp:39:28: warning: unused parameter ‘obj1’ [-Wunused-parameter]
 void Thread_Func(MyClass1 &obj1, MyClass2 obj2)
                            ^
source_file.cpp:39:43: warning: unused parameter ‘obj2’ [-Wunused-parameter]
 void Thread_Func(MyClass1 &obj1, MyClass2 obj2)
                                           ^
Error(s):
*** Error in `/var/www/service/usercode/1975631137/a.out': double free or corruption (!prev): 0x0000000002006c90 ***
*** Error in `/var/www/service/usercode/1975631137/a.out': double free or corruption (!prev): 0x0000000002006c90 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f6eca3827e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x7fe0a)[0x7f6eca38ae0a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f6eca38e98c]
/var/www/service/usercode/1975631137/a.out[0x401188]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f6eca32b830]
/var/www/service/usercode/1975631137/a.out[0x4013f9]
======= Memory map: ========
00400000-00402000 r-xp 00000000 b6:68991 5955860                         /var/www/service/usercode/1975631137/a.out
00602000-00603000 r--p 00002000 b6:68991 5955860                         /var/www/service/usercode/1975631137/a.out
00603000-00604000 rw-p 00003000 b6:68991 5955860                         /var/www/service/usercode/1975631137/a.out
01ff5000-02027000 rw-p 00000000 00:00 0                                  [heap]
7f6ec0000000-7f6ec0021000 rw-p 00000000 00:00 0 
7f6ec0021000-7f6ec4000000 ---p 00000000 00:00 0 
7f6ec40a3000-7f6ec40a4000 ---p 00000000 00:00 0 
7f6ec40a4000-7f6eca002000 rw-p 00000000 00:00 0 
7f6eca002000-7f6eca10a000 r-xp 00000000 b6:68991 10854                   /lib/x86_64-linux-gnu/libm-2.23.so
7f6eca10a000-7f6eca309000 ---p 00108000 b6:68991 10854                   /lib/x86_64-linux-gnu/libm-2.23.so
7f6eca309000-7f6eca30a000 r--p 00107000 b6:68991 10854                   /lib/x86_64-linux-gnu/libm-2.23.so
7f6eca30a000-7f6eca30b000 rw-p 00108000 b6:68991 10854                   /lib/x86_64-linux-gnu/libm-2.23.so
7f6eca30b000-7f6eca4ca000 r-xp 00000000 b6:68991 10849                   /lib/x86_64-linux-gnu/libc-2.23.so
7f6eca4ca000-7f6eca6ca000 ---p 001bf000 b6:68991 10849                   /lib/x86_64-linux-gnu/libc-2.23.so
7f6eca6ca000-7f6eca6ce000 r--p 001bf000 b6:68991 10849                   /lib/x86_64-linux-gnu/libc-2.23.so
7f6eca6ce000-7f6eca6d0000 rw-p 001c3000 b6:68991 10849                   /lib/x86_64-linux-gnu/libc-2.23.so
7f6eca6d0000-7f6eca6d4000 rw-p 00000000 00:00 0 
7f6eca6d4000-7f6eca6ec000 r-xp 00000000 b6:68991 10855                   /lib/x86_64-linux-gnu/libpthread-2.23.so
7f6eca6ec000-7f6eca8eb000 ---p 00018000 b6:68991 10855                   /lib/x86_64-linux-gnu/libpthread-2.23.so
7f6eca8eb000-7f6eca8ec000 r--p 00017000 b6:68991 10855                   /lib/x86_64-linux-gnu/libpthread-2.23.so
7f6eca8ec000-7f6eca8ed000 rw-p 00018000 b6:68991 10855                   /lib/x86_64-linux-gnu/libpthread-2.23.so
7f6eca8ed000-7f6eca8f1000 rw-p 00000000 00:00 0 
7f6eca8f1000-7f6eca907000 r-xp 00000000 b6:68991 105                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7f6eca907000-7f6ecab06000 ---p 00016000 b6:68991 105                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7f6ecab06000-7f6ecab07000 rw-p 00015000 b6:68991 105                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7f6ecab07000-7f6ecac79000 r-xp 00000000 b6:68991 3213                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f6ecac79000-7f6ecae79000 ---p 00172000 b6:68991 3213                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f6ecae79000-7f6ecae83000 r--p 00172000 b6:68991 3213                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f6ecae83000-7f6ecae85000 rw-p 0017c000 b6:68991 3213                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f6ecae85000-7f6ecae89000 rw-p 00000000 00:00 0 
7f6ecae89000-7f6ecaeaf000 r-xp 00000000 b6:68991 10838                   /lib/x86_64-linux-gnu/ld-2.23.so
7f6ecb07a000-7f6ecb080000 rw-p 00000000 00:00 0 
7f6ecb0aa000-7f6ecb0ab000 rw-p 00000000 00:00 0 
7f6ecb0ac000-7f6ecb0ae000 rw-p 00000000 00:00 0 
7f6ecb0ae000-7f6ecb0af000 r--p 00025000 b6:68991 10838                   /lib/x86_64-linux-gnu/ld-2.23.so
7f6ecb0af000-7f6ecb0b0000 rw-p 00026000 b6:68991 10838                   /lib/x86_64-linux-gnu/ld-2.23.so
7f6ecb0b0000-7f6ecb0b1000 rw-p 00000000 00:00 0 
7ffff0da9000-7ffff0dbe000 rw-p 00000000 00:00 0                          [stack]
7ffff0dc4000-7ffff0dc6000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

Abort signal from abort(3) (SIGABRT)
1
6739 / 4537 / 1840
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
24.12.2019, 11:29 5
Без неё у тебя obj2 копировался
0
2 / 2 / 0
Регистрация: 27.11.2016
Сообщений: 62
24.12.2019, 11:44  [ТС] 6
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Ссылку потерял Threads.emplace_back([&obj1, &obj2]()
Как раз не потерял, мне именно что нужна копия объекта

Добавлено через 33 секунды
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Без неё у тебя obj2 копировался
Я знаю, так задумано

Добавлено через 2 минуты
Цитата Сообщение от hoggy Посмотреть сообщение
вообще то, ты бы и сам бы мог сразу это понять.
если бы включил режим предупреждений на полную мощность,
и просто прочитал что тебе пишет компилятор.
Спасибо за советы, учту.

Цитата Сообщение от hoggy Посмотреть сообщение
у тебя тут нарушение правила "3х":
если тебе понадобился деструктор,
значит тебе нужен конструктор копии и оператор= тоже.
Понял, спасибо, буду править

Добавлено через 2 минуты
hoggy, ок, а почему вылетает та же ошибка при вызове sleep_for?
0
6739 / 4537 / 1840
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
24.12.2019, 11:49 7
Цитата Сообщение от Юрий Мамонтов Посмотреть сообщение
hoggy, ок, а почему вылетает та же ошибка при вызове sleep_for?
у тебя ошибка вылетает при вызове деструктора obj1, который копируется/удаляется несколько раз. Всё остальное работает нормально. Сделай конструктор копирования и всё.
На sleep_for - потому что основной поток выполняет именно эту инструкцию, когда в другом потоке возникает ошибка
1
2 / 2 / 0
Регистрация: 27.11.2016
Сообщений: 62
24.12.2019, 11:52  [ТС] 8
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
у тебя ошибка вылетает при вызове деструктора obj1, который копируется/удаляется несколько раз. Всё остальное работает нормально. Сделай конструктор копирования и всё.
На sleep_for - потому что основной поток выполняет именно эту инструкцию, когда в другом потоке возникает ошибка
oleg-m1973, понял! Спасибо большое!
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
24.12.2019, 11:52

Сегфолт при попытке вызвать memcpy
Почему тут вылетает сегфолт? #include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;string.h&gt; int...

EntryPointNotFoundException при попытке вызвать метод из C++ DLL
Может быть объяснит кто-нибудь почему у меня не получается запустить метод написанный на языке с++...

Исключение при попытке вызвать QFileDialog::getOpenFileName
Доброго времени суток. При попытке выбора файла с помощью QFileDialog::getOpenFileName Получаю...

Ошибка "Integrity constraint violation" при запросе INNER JOIN LEFT JOIN
это запрос на вывод категорий в каждой категории есть файлы и для каждой категории я хочу вывести...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.