Oleg
Oleg

Reputation: 3200

multithread std::shared_ptr read / write

I have a double free bug using std::shared_ptr and trying to get know why. I am using shared_ptr in multithread environment , one thread sometimes replaces some element in a global array

std::shared_ptr<Bucket>  globalTable[100]; // global elements storage

using:

globalTable[idx].reset(newBucket);

and the other thread reads this table sometimes using :

std::shared_ptr<Bucket> bkt(globalTable[pIdx]);
// do calculations with bkt-> items

After this I am receiving double-free error, and AddressSanitizer says that the second code tries to free an object that was destroyed by the first one . How it is possible ? As I know shared_ptr must be completly thread safe.

Upvotes: 2

Views: 1603

Answers (2)

Gabriel
Gabriel

Reputation: 3584

Reset does not guarantee you thread saefty.

Assignments and reference counting are thread safe as explained here

To satisfy thread safety requirements, the reference counters are typically incremented using an equivalent of std::atomic::fetch_add with std::memory_order_relaxed (decrementing requires stronger ordering to safely destroy the control block).

If multiple threads access same shared_ptr you can have a race condition.

If multiple threads of execution access the same shared_ptr without synchronization and any of those accesses uses a non-const member function of shared_ptr then a data race will occur; the shared_ptr overloads of atomic functions can be used to prevent the data race.

Your function reset is non const so falls on that category. You need to use mutex or another synchronization mechanism.

http://en.cppreference.com/w/cpp/memory/shared_ptr

Upvotes: 2

Deduplicator
Deduplicator

Reputation: 45654

Not all operations on a std::shared_ptr are thread-safe.

Specifically, the reference-counts are managed atomically, but it's your responsibility to make sure the std::shared_ptr instance you access is not concurrently modified.

You fail that responsibility, resulting in a data-race and the expected undefined behavior, manifesting as a double-free in your case.

Upvotes: 3

Related Questions