Run this test case (sorry for the length, was not able to make it smaller): #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <string.h> #include <string> #include <list> using namespace std; char* list2byteArray() { // count data amount size_t data_size = 24; // copy data char *data = new char[data_size]; for (size_t i = 0; i < data_size; i++) { data[i] = 'a'; } data[data_size - 1] = 0; char *ret = strdup(data); delete[] data; return ret; } int addRecord() { char *data = list2byteArray(); usleep(100); free(data); return 0; } void *fillTable(void *ptr) { for (int i = 0; i < 100; i++) { string id("000"); id.append(1, 'a' + i); list<string> record; record.push_back("some data"); addRecord(); } usleep(1000 * 1000); return NULL; } int main(int argc, char* argv[]) { int err; pthread_t thread1; pthread_t thread2; // create err = pthread_create(&thread1, NULL, &fillTable, NULL); if (err != 0) throw string("failed to create a thread."); err = pthread_create(&thread2, NULL, &fillTable, NULL); if (err != 0) throw string("failed to create a thread."); // join err = pthread_join(thread1, NULL); if (err != 0) throw string("Thread::join(): failed to join."); err = pthread_join(thread2, NULL); if (err != 0) throw string("Thread::join(): failed to join."); } Compiled with > g++ -std=c++11 -O0 -g test.cpp -lpthread -o test analysed with > valgrind --tool=drd ./test GCC-Information: g++ (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2 Valgrind SVN revision r13645. Compiled using default configuration. Reproducible: Always Steps to Reproduce: 1. Compile as described 2. Run as described Actual Results: Analysis result is: ==28897== drd, a thread error detector ==28897== Copyright (C) 2006-2013, and GNU GPL'd, by Bart Van Assche. ==28897== Using Valgrind-3.9.0.SVN and LibVEX; rerun with -h for copyright info ==28897== Command: ./test ==28897== ==28897== Thread 3: ==28897== Conflicting store by thread 3 at 0x0643325b size 1 ==28897== at 0x51194D8: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17) ==28897== by 0x511BE28: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17) ==28897== by 0x511BE72: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17) ==28897== by 0x4010AA: fillTable(void*) (main.cpp:38) ==28897== by 0x4C2ED64: vgDrd_thread_wrapper (drd_pthread_intercepts.c:355) ==28897== by 0x4E48E99: start_thread (pthread_create.c:308) ==28897== by 0x566ACCC: clone (clone.S:112) ==28897== Address 0x643325b is at offset 27 from 0x6433240. Allocation context: ==28897== at 0x4C2E2CB: operator new(unsigned long) (vg_replace_malloc.c:319) ==28897== by 0x511A3B8: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17) ==28897== by 0x511BD94: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17) ==28897== by 0x511BE72: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17) ==28897== by 0x4010AA: fillTable(void*) (main.cpp:38) ==28897== by 0x4C2ED64: vgDrd_thread_wrapper (drd_pthread_intercepts.c:355) ==28897== by 0x4E48E99: start_thread (pthread_create.c:308) ==28897== by 0x566ACCC: clone (clone.S:112) ==28897== Other segment start (thread 2) ==28897== at 0x4C3274E: pthread_mutex_unlock (drd_pthread_intercepts.c:680) ==28897== by 0x4C2ED5E: vgDrd_thread_wrapper (drd_pthread_intercepts.c:236) ==28897== by 0x4E48E99: start_thread (pthread_create.c:308) ==28897== by 0x566ACCC: clone (clone.S:112) ==28897== Other segment end (thread 2) ==28897== at 0x563684D: ??? (syscall-template.S:82) ==28897== by 0x5664783: usleep (usleep.c:33) ==28897== by 0x40105D: addRecord() (main.cpp:29) ==28897== by 0x40112A: fillTable(void*) (main.cpp:43) ==28897== by 0x4C2ED64: vgDrd_thread_wrapper (drd_pthread_intercepts.c:355) ==28897== by 0x4E48E99: start_thread (pthread_create.c:308) ==28897== by 0x566ACCC: clone (clone.S:112) ==28897== ==28897== Thread 2: ==28897== Conflicting store by thread 2 at 0x064334ac size 1 ==28897== at 0x51194D8: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17) ==28897== by 0x511A6FE: std::string::_M_mutate(unsigned long, unsigned long, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17) ==28897== by 0x511A9B4: std::string::_M_replace_aux(unsigned long, unsigned long, unsigned long, char) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17) ==28897== by 0x401731: std::string& std::string::_M_replace_dispatch<int>(__gnu_cxx::__normal_iterator<char*, std::string>, __gnu_cxx::__normal_iterator<char*, std::string>, int, int, std::__true_type) (basic_string.h:1699) ==28897== by 0x40157B: std::string& std::string::replace<int>(__gnu_cxx::__normal_iterator<char*, std::string>, __gnu_cxx::__normal_iterator<char*, std::string>, int, int) (basic_string.h:1627) ==28897== by 0x401488: std::string& std::string::append<int>(int, int) (basic_string.h:1042) ==28897== by 0x4010CD: fillTable(void*) (main.cpp:39) ==28897== by 0x4C2ED64: vgDrd_thread_wrapper (drd_pthread_intercepts.c:355) ==28897== by 0x4E48E99: start_thread (pthread_create.c:308) ==28897== by 0x566ACCC: clone (clone.S:112) ==28897== Address 0x64334ac is at offset 28 from 0x6433490. Allocation context: ==28897== at 0x4C2E2CB: operator new(unsigned long) (vg_replace_malloc.c:319) ==28897== by 0x511A3B8: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17) ==28897== by 0x511A5B2: std::string::_M_mutate(unsigned long, unsigned long, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17) ==28897== by 0x511A9B4: std::string::_M_replace_aux(unsigned long, unsigned long, unsigned long, char) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17) ==28897== by 0x401731: std::string& std::string::_M_replace_dispatch<int>(__gnu_cxx::__normal_iterator<char*, std::string>, __gnu_cxx::__normal_iterator<char*, std::string>, int, int, std::__true_type) (basic_string.h:1699) ==28897== by 0x40157B: std::string& std::string::replace<int>(__gnu_cxx::__normal_iterator<char*, std::string>, __gnu_cxx::__normal_iterator<char*, std::string>, int, int) (basic_string.h:1627) ==28897== by 0x401488: std::string& std::string::append<int>(int, int) (basic_string.h:1042) ==28897== by 0x4010CD: fillTable(void*) (main.cpp:39) ==28897== by 0x4C2ED64: vgDrd_thread_wrapper (drd_pthread_intercepts.c:355) ==28897== by 0x4E48E99: start_thread (pthread_create.c:308) ==28897== by 0x566ACCC: clone (clone.S:112) ==28897== Other segment start (thread 3) ==28897== at 0x4C3274E: pthread_mutex_unlock (drd_pthread_intercepts.c:680) ==28897== by 0x4C2ED5E: vgDrd_thread_wrapper (drd_pthread_intercepts.c:236) ==28897== by 0x4E48E99: start_thread (pthread_create.c:308) ==28897== by 0x566ACCC: clone (clone.S:112) ==28897== Other segment end (thread 3) ==28897== at 0x563684D: ??? (syscall-template.S:82) ==28897== by 0x5664783: usleep (usleep.c:33) ==28897== by 0x40105D: addRecord() (main.cpp:29) ==28897== by 0x40112A: fillTable(void*) (main.cpp:43) ==28897== by 0x4C2ED64: vgDrd_thread_wrapper (drd_pthread_intercepts.c:355) ==28897== by 0x4E48E99: start_thread (pthread_create.c:308) ==28897== by 0x566ACCC: clone (clone.S:112) ==28897== ==28897== Conflicting store by thread 2 at 0x064334ab size 1 ==28897== at 0x511AA00: std::string::_M_replace_aux(unsigned long, unsigned long, unsigned long, char) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17) ==28897== by 0x401731: std::string& std::string::_M_replace_dispatch<int>(__gnu_cxx::__normal_iterator<char*, std::string>, __gnu_cxx::__normal_iterator<char*, std::string>, int, int, std::__true_type) (basic_string.h:1699) ==28897== by 0x40157B: std::string& std::string::replace<int>(__gnu_cxx::__normal_iterator<char*, std::string>, __gnu_cxx::__normal_iterator<char*, std::string>, int, int) (basic_string.h:1627) ==28897== by 0x401488: std::string& std::string::append<int>(int, int) (basic_string.h:1042) ==28897== by 0x4010CD: fillTable(void*) (main.cpp:39) ==28897== by 0x4C2ED64: vgDrd_thread_wrapper (drd_pthread_intercepts.c:355) ==28897== by 0x4E48E99: start_thread (pthread_create.c:308) ==28897== by 0x566ACCC: clone (clone.S:112) ==28897== Address 0x64334ab is at offset 27 from 0x6433490. Allocation context: ==28897== at 0x4C2E2CB: operator new(unsigned long) (vg_replace_malloc.c:319) ==28897== by 0x511A3B8: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17) ==28897== by 0x511A5B2: std::string::_M_mutate(unsigned long, unsigned long, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17) ==28897== by 0x511A9B4: std::string::_M_replace_aux(unsigned long, unsigned long, unsigned long, char) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17) ==28897== by 0x401731: std::string& std::string::_M_replace_dispatch<int>(__gnu_cxx::__normal_iterator<char*, std::string>, __gnu_cxx::__normal_iterator<char*, std::string>, int, int, std::__true_type) (basic_string.h:1699) ==28897== by 0x40157B: std::string& std::string::replace<int>(__gnu_cxx::__normal_iterator<char*, std::string>, __gnu_cxx::__normal_iterator<char*, std::string>, int, int) (basic_string.h:1627) ==28897== by 0x401488: std::string& std::string::append<int>(int, int) (basic_string.h:1042) ==28897== by 0x4010CD: fillTable(void*) (main.cpp:39) ==28897== by 0x4C2ED64: vgDrd_thread_wrapper (drd_pthread_intercepts.c:355) ==28897== by 0x4E48E99: start_thread (pthread_create.c:308) ==28897== by 0x566ACCC: clone (clone.S:112) ==28897== Other segment start (thread 3) ==28897== at 0x4C3274E: pthread_mutex_unlock (drd_pthread_intercepts.c:680) ==28897== by 0x4C2ED5E: vgDrd_thread_wrapper (drd_pthread_intercepts.c:236) ==28897== by 0x4E48E99: start_thread (pthread_create.c:308) ==28897== by 0x566ACCC: clone (clone.S:112) ==28897== Other segment end (thread 3) ==28897== at 0x563684D: ??? (syscall-template.S:82) ==28897== by 0x5664783: usleep (usleep.c:33) ==28897== by 0x40105D: addRecord() (main.cpp:29) ==28897== by 0x40112A: fillTable(void*) (main.cpp:43) ==28897== by 0x4C2ED64: vgDrd_thread_wrapper (drd_pthread_intercepts.c:355) ==28897== by 0x4E48E99: start_thread (pthread_create.c:308) ==28897== by 0x566ACCC: clone (clone.S:112) ==28897== ==28897== ==28897== For counts of detected and suppressed errors, rerun with: -v ==28897== ERROR SUMMARY: 5 errors from 3 contexts (suppressed: 177 from 75) Expected Results: No errors expected.
Thanks for the report and for the test case. It would be appreciated if you could help testing the following candidate fix: drd: Avoid that optimized strlen() implementations trigger false positive race reports (#326091) diff --git a/drd/drd_strmem_intercepts.c b/drd/drd_strmem_intercepts.c index d77e824..7248907 100644 --- a/drd/drd_strmem_intercepts.c +++ b/drd/drd_strmem_intercepts.c @@ -70,6 +70,7 @@ STRLEN(VG_Z_LIBC_SONAME, strlen) STRLEN(VG_Z_LD_LINUX_SO_2, strlen) STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen) + STRLEN(VG_Z_LIBC_SONAME, __GI_strlen) #elif defined(VGO_darwin) STRLEN(VG_Z_LIBC_SONAME, strlen) #endif
Note: the above patch has been checked in as r13664 on the trunk.
Confirmed: error is not reported any more