Reputation: 1
I am getting into threading in C++ and was going some testing and got this error.
Here is my code:
#include <iostream>
#include <thread>
#include <unordered_map>
#include <string>
#include <vector>
using namespace std;
static vector<string> thisVector;
void thread1() {
for (int i = 0; i < 400; i++){
thisVector.push_back(to_string(i));
}
cout << "Finished 1" << endl;
return;
}
void thread2() {
for (int i = 0; i < 400; i++){
thisVector.push_back(to_string(i));
}
cout << "Finished 2" << endl;
return;
}
int main(int argc, const char * argv[]) {
thread first(thread1);
thread second(thread2);
first.join();
second.join();
cout << "done threading" << endl;
cout << thisVector.size() << endl;
return 0;
}
The weird thing is, sometimes I get the correct output, so 800. Sometimes I get a number slightly lower than that for I don't know what reason??? And sometimes I get the following error:
malloc: *** error for object 0x100400028: pointer being freed was not allocated
Any help would be greatly appreciated!
Thanks
Upvotes: 0
Views: 902
Reputation: 19
You can try something like this:
#include <iostream>
#include <thread>
#include <unordered_map>
#include <string>
#include <vector>
using namespace std;
static vector<string> thisVector;
//Global MUTEX
mutex mv;
//
void thread1() {
for (int i = 0; i < 400; i++){
//Lock before and unlock after push back
mv.lock();
thisVector.push_back(to_string(i));
mv.unlock();
}
cout << "Finished 1" << endl;
return;
}
void thread2() {
for (int i = 0; i < 400; i++){
mv.lock();
thisVector.push_back(to_string(i));
mv.unlock();
}
cout << "Finished 2" << endl;
return;
}
int main(int argc, const char * argv[]) {
thread first(thread1);
thread second(thread2);
first.join();
second.join();
cout << "done threading" << endl;
cout << thisVector.size() << endl;
return 0;
}
Upvotes: 0
Reputation: 11162
It is worth reading The C++ Programming Language, it covers subjects of interest like : threads, tasks, but also at higher conceptual level future/promise, packaged_task, async.
In your case, you don't only deal with concurrency. You have to deal with shared data of concurrent threads. The way you programmed it does not guarantee any order of execution. That is why you get those strange results.
The error message you mentioned is likely to be because of concurrent access to the shared vector and it says what is wrong: a pointer is being freed (delete), but was not allocated beforehand. You don't see the pointer, it's an internal member of vector.
Your solution is to use a mutex to make sure that whenever a data is pushed back into the vector it does not get interrupted by the other concurrent thread and finishes appropriately, so that the next push_back starts only when the previous one has finished.
You can use a global variable for mutex. Then you need to deal appropriately with locking/unlocking, i.e. you must say when to acquire a mutex (before push_back) and when to release it (after push_back). Since you use only one mutex this should be fairly simple and should work.
Upvotes: 0
Reputation: 118340
A std::vector
is not thread safe. You have two execution threads modifying the same std::vector
concurrently. Operations on a std::vector
should, in this case, be protected by a mutex.
The result of this is undefined behavior. As you've observed, sometimes it might work, sometimes wrong results get produced but the program completes successfully, sometimes the program crashes. This is what "undefined behavior" means.
Upvotes: 1