Mict
Mict

Reputation: 1

C++ Threading error: pointer being freed was not allocated

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

Answers (3)

Daniel Augusta
Daniel Augusta

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

Ely
Ely

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

Sam Varshavchik
Sam Varshavchik

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

Related Questions