0

this is more a general question rather than a specific coding problem. Does (and if yes, how) C++ avoid that multiple threads try to allocate the same memory adresses?

For example:

#include <vector>
#include <thread>

int main() {
std::vector<int> x, y;

std::thread do_work([&x] () {
    /* push_back a lot of ints to x */
});

/* push_back a lot of ints to y */
do_work.join()

/* do more stuff */ }

When the two vectors allocate memory because they reached their capacity, is it possible that both vectors try to allocate the same piece of memory since the heap is shared among threads? Is code like this unsafe because it potentially creates races?

Urwald
  • 343
  • 1
  • 10
  • 3
    Memory allocation is thread-safe. That guarantee goes all the way down to the operating system itself. – Some programmer dude Sep 26 '21 at 09:37
  • As mentioned in the following page, starting with C++11 those guarantees should exist: https://en.cppreference.com/w/cpp/memory/c/malloc – fabian Sep 26 '21 at 09:43
  • 1
    When passing data to threads, doing so by reference may be tricky. In this case it is ok because of your call to join. A more generic pattern is to allocate a shared_ptr to a vector and pass that shared_ptr by value. If the thread then outlives the scope in which you allocated the memory the shared_ptr (copy) will keep your data alive. – Pepijn Kramer Sep 26 '21 at 10:00
  • Thanks a lot guys for your very valuable comments. – Urwald Sep 26 '21 at 10:23

1 Answers1

2

Allocation memory (via malloc/new/HeapAlloc and such) are thread-safe by default as long as you've compiled you application against thread safe runtimes (which you will, unless you explicitly change that).

Each vector will get its own slice of memory whenever they resize, but once a slice is freed any (other) thread could end up getting it the next time an allocation occurs.

You could, however, mess things up if you replace your allocators. Like if you overload the "new operator" and you're no longer getting memory for a thread safe source. https://en.cppreference.com/w/cpp/memory/new/operator_new

You could also opt to use a non-thread-safe version of malloc if you replace if via some sort of library-preload on Linux (Overriding 'malloc' using the LD_PRELOAD mechanism).

But assuming you're not doing any of that, the default implementation of user-space allocators (new/malloc) are thread safe, and OS level allocators (VirtualAlloc/mmap) are always thread safe.

Sven Almgren
  • 183
  • 10