I am encountering a problem that Valgrind/Helgrind does not recognize std::future as mentioned in this answer. In that answer, the solution is to use clang and libc++ instead of gcc/libstdc++.
I use Ubuntu 18.04 and use apt to install clang 6.0.0, but when I run
clang++ helgrind_test.cc -lpthread -std=c++11 -stdlib=libc++ -o helgrind_test
I got the following error:
helgrind_test.cc:1:10: fatal error: 'future' file not found
#include <future>
^~~~~~~~
1 error generated.
Using libstdc++ will get the code compiles but it does not remove helgrind error.
Can you help me figure out what's going wrong?
The helgrind_test.cc source code is here:
#include <future>
#include <iostream>
#include <mutex>
#define _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(A) ANNOTATE_HAPPENS_BEFORE(A)
#define _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(A) ANNOTATE_HAPPENS_AFTER(A)
using namespace std;
promise<int> promise_;
void run() {
int result = 0;
for(int i = 0 ; i < 100000;++i) {
result += i;
}
promise_.set_value(result);
}
int main() {
auto f = promise_.get_future();
thread another(run);
another.detach();
cout << f.get() << endl;
}
And the error I got from helgrind is like:
==73696== Possible data race during read of size 4 at 0x5DA2D00 by thread #1
==73696== Locks held: none
==73696== at 0x40215B: std::future<int>::get() (in /home/cc/helgrind_test)
==73696== by 0x401BF3: main (in /home/cc/helgrind_test)
==73696==
==73696== This conflicts with a previous write of size 4 by thread #2
==73696== Locks held: none
==73696== at 0x40529A: std::__future_base::_Result<int>::_M_set(int const&) (in /home/cc/helgrind_test)
==73696== by 0x4051CD: std::__future_base::_State_baseV2::_Setter<int, int const&>::operator()() const (in /home/cc/helgrind_test)
==73696== by 0x404FCE: std::_Function_handler<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> (), std::__future_base::_State_baseV2::_Setter<int, int const&> >::_M_invoke(std::_Any_data const&) (in /home/cc/helgrind_test)
==73696== by 0x404E9C: std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>::operator()() const (in /home/cc/helgrind_test)
==73696== by 0x404BBB: std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*) (in /home/cc/helgrind_test)
==73696== by 0x404E40: void std::__invoke_impl<void, void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::__invoke_memfun_deref, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) (in /home/cc/helgrind_test)
==73696== by 0x404D4B: std::__invoke_result<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>::type std::__invoke<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) (in /home/cc/helgrind_test)
==73696== by 0x404CE5: void std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#1}::operator()() const (in /home/cc/helgrind_test)
==73696== Address 0x5da2d00 is 16 bytes inside a block of size 24 alloc'd
==73696== at 0x4C3159F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==73696== by 0x401E63: std::promise<int>::promise() (in /home/cc/helgrind_test)
==73696== by 0x401A16: __cxx_global_var_init.1 (in /home/cc/helgrind_test)
==73696== by 0x401A5D: _GLOBAL__sub_I_helgrind_test.cc (in /home/cc/helgrind_test)
==73696== by 0x40691C: __libc_csu_init (in /home/cc/helgrind_test)
==73696== by 0x59C1B27: (below main) (libc-start.c:266)
==73696== Block was alloc'd by thread #1