Reputation: 13
I am getting Segmentation fault: 11 while Creating a Queue using Vector of Threads, could you please help me to fix.
#include <thread>
#include <queue>
#include <iostream>
using namespace std;
int tcount = 0;
template <typename T>
void thread_spawn_q(queue<T> &q)
{
vector<thread> ths;
for (int i = 1; i <= 20000; i++)
{
ths.push_back(thread(static_cast<void (queue<T>::*)(T &&)>(&queue<T>::push), &q, to_string(i)));
++tcount;
}
for (auto &th : ths)
{
th.join();
}
}
int main()
{
queue<string> q = queue<string>();
thread_spawn_q(q);
cout << "tcount:" << tcount << endl;
return 0;
}
Edit#1
Making only 5 threads instead of 20000. I am still getting Segfault intermittently and also error: pointer being freed was not allocated.
cpptest$ ./sof_test2.exec
tcount:5
cpptest$ ./sof_test2.exec
tcount:5
sof_test2.exec(77351,0x11944be00) malloc: *** error for object 0x100000010: pointer being freed was not allocated
sof_test2.exec(77351,0x11944be00) malloc: *** set a breakpoint in malloc_error_break to debug
Abort trap: 6
cpptest$ ./sof_test2.exec
tcount:5
cpptest$ ./sof_test2.exec
tcount:5
sof_test2.exec(77358,0x10dbd9e00) malloc: *** error for object 0x2000000000000: pointer being freed was not allocated
sof_test2.exec(77358,0x10dbd9e00) malloc: *** set a breakpoint in malloc_error_break to debug
Abort trap: 6
cpptest$ ./sof_test2.exec
tcount:5
cpptest$ ./sof_test2.exec
Segmentation fault: 11
cpptest$ ./sof_test2.exec
tcount:5
sof_test2.exec(77368,0x10f1f7e00) malloc: *** error for object 0x100007fcb4c405dc: pointer being freed was not allocated
sof_test2.exec(77368,0x10f1f7e00) malloc: *** set a breakpoint in malloc_error_break to debug
Abort trap: 6
Upvotes: 1
Views: 113
Reputation: 9703
As @273K says: "standard containers are not thread safe": you need to syncronize using a mutex, like this:
#include <iostream>
#include <mutex>
#include <queue>
#include <thread>
int tcount{0};
template <typename T>
void thread_spawn_q(std::queue<T> &q)
{
std::vector<std::thread> ths;
std::mutex mutex;
for (int i = 1; i <= 5; i++)
{
// Your version: ths.push_back(thread(static_cast<void (queue<T>::*)(T &&)>(&queue<T>::push), &q, to_string(i)));
/* Easier-to-read version of same:
ths.push_back(std::thread(
[&q](int i) {
q.push(std::to_string(i));
},
i));*/
// Correct version, using a mutex
ths.push_back(std::thread(
[&q, &mutex](int i) {
// We still call std::to_string in parallel...
auto s = std::to_string(i);
std::unique_lock lock{mutex};
// ... but only one thread at a time is looking at q while it's being modified:
q.push(std::move(s));
},
i));
++tcount;
}
for (auto &th : ths)
{
th.join();
}
}
int main()
{
auto q = std::queue<std::string>();
thread_spawn_q(q);
std::cout << "tcount:" << tcount << std::endl;
return 0;
}
https://godbolt.org/z/KzWKqsz9n
Upvotes: 1