This example #include <future> #include <iostream> int main() { char counter = 0; auto future1 = std::async(std::launch::async, [&]() { counter++; }); auto future2 = std::async(std::launch::async, [&]() { return counter; }); future1.wait(); // Cast to int to print it as a numerical value rather than a character std::cout << (int)future2.get(); } from https://github.com/knatten/cpp-brain-teasers.git generates errors with both Helgrind and Thread Sanitizer on Linux with g++ and libstdc++. Nothing with Helgrind on FreeBSD with clang++/libc++. No error with DRD. /home/paulf/tools/valgrind/bin/valgrind --tool=drd --check-stack-var=yes -q ./back-from-the-future 1 I think that this is because the memory for the captured reference to counter is neither on the stack of the lambda nor on the heap.
I've been debugging drd_trace_store_1 and drd_trace_load_1 For the load if (DRD_(running_thread_is_recording_loads)() && (s_check_stack_accesses || ! DRD_(thread_address_on_stack)(addr)) && bm_access_load_1_triggers_conflict(addr) && ! DRD_(is_suppressed)(addr, addr + 1)) { drd_report_race(addr, 1, eLoad); } DRD_(thread_address_on_stack)(addr) is false (the address is above the call frame of the lambda in the call frame of main). I need to debug the bitmaps related to this address to see why no conflict is detected.
I also tried this with some heap memory and still no error detected.