我正在学习不同的记忆顺序。
\n我有这段代码,它可以工作并通过 GCC 和 Clang 的线程清理程序:
\n#include <atomic>\n#include <iostream>\n#include <future>\n \nint state = 0;\nstd::atomic_int a = 0;\n\nvoid foo(int from, int to) \n{\n for (int i = 0; i < 10; i++)\n {\n while (a.load(std::memory_order_acquire) != from) {}\n state++;\n a.store(to, std::memory_order_release);\n }\n}\n\nint main()\n{ \n auto x = std::async(std::launch::async, foo, 0, 1);\n auto y = std::async(std::launch::async, foo, 1, 0);\n}\nRun Code Online (Sandbox Code Playgroud)\n我认为如果它最终没有返回,则“获取”加载是不必要的from,那么“获取”负载是不必要的,因此我决定使用“宽松”负载,然后使用“获取”栅栏。
我期望它能工作,但它被线程清理程序拒绝了,线程清理程序声称并发state++是数据竞争。
#include <atomic>\n#include <iostream>\n#include <future>\n \nint state = 0;\nstd::atomic_int …Run Code Online (Sandbox Code Playgroud) 我已将其归结为一个简单的自包含示例.主线程将1000个项目排队,并且工作线程尝试同时出列.ThreadSanitizer抱怨在其中一个元素的读取和写入之间存在竞争,即使存在一个保护它们的获取释放内存屏障序列.
#include <atomic>
#include <thread>
#include <cassert>
struct FakeQueue
{
int items[1000];
std::atomic<int> m_enqueueIndex;
int m_dequeueIndex;
FakeQueue() : m_enqueueIndex(0), m_dequeueIndex(0) { }
void enqueue(int x)
{
auto tail = m_enqueueIndex.load(std::memory_order_relaxed);
items[tail] = x; // <- element written
m_enqueueIndex.store(tail + 1, std::memory_order_release);
}
bool try_dequeue(int& x)
{
auto tail = m_enqueueIndex.load(std::memory_order_acquire);
assert(tail >= m_dequeueIndex);
if (tail == m_dequeueIndex)
return false;
x = items[m_dequeueIndex]; // <- element read -- tsan says race!
++m_dequeueIndex;
return true;
}
};
FakeQueue q;
int main()
{ …Run Code Online (Sandbox Code Playgroud) clang++和消毒剂都会g++针对这个简单代码的数据竞争产生类似的警告。难道是虚惊一场?问题是什么?
代码:
#include <thread>
struct A
{
void operator()()
{
}
};
struct B
{
void operator()()
{
}
};
int main(void)
{
// callable objects are created and moved into thread
std::thread t1(A{});
std::thread t2(B{});
t1.join();
t2.join();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译标志:
-pthread -O0 -g -fsanitize=thread -fsanitize=undefined
Run Code Online (Sandbox Code Playgroud)
消毒剂输出g++:
==================
WARNING: ThreadSanitizer: data race (pid=80173)
Write of size 8 at 0x7b0400000800 by thread T2:
#0 pipe ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1726 (libtsan.so.0+0x3ea28)
#1 __sanitizer::IsAccessibleMemoryRange(unsigned long, unsigned long) ../../../../src/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp:276 (libubsan.so.1+0x20102)
#2 …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用g ++和线程消毒剂,我认为我得到了误报.这是真的吗,还是我犯了一些大错?
程序(剪切和粘贴来自Anthony Williams:C++ Concurrency in Action,第145页,清单5.13)
#include <atomic>
#include <thread>
#include <assert.h>
bool x=false;
std::atomic<bool> y;
std::atomic<int> z;
void write_x_then_y()
{
x=true;
std::atomic_thread_fence(std::memory_order_release);
y.store(true,std::memory_order_relaxed);
}
void read_y_then_x()
{
while(!y.load(std::memory_order_relaxed));
std::atomic_thread_fence(std::memory_order_acquire);
if(x)
++z;
}
int main()
{
x=false;
y=false;
z=0;
std::thread a(write_x_then_y);
std::thread b(read_y_then_x);
a.join();
b.join();
assert(z.load()!=0);
}
Run Code Online (Sandbox Code Playgroud)
编译:
g++ -o a -g -Og -pthread a.cpp -fsanitize=thread
Run Code Online (Sandbox Code Playgroud)
g ++版本
~/build/px> g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/6.1.1/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix …Run Code Online (Sandbox Code Playgroud) Xcode 8采用了Thread Sanitizer,这是一种用于检测竞争条件和其他线程相关问题的工具.
我正在尝试针对我的项目运行此项,并且正在检测第三方二进制库的许多问题.这些问题在我自己的代码中是压倒性的,在供应商修复它之前我无法替换二进制库.
如何在Xcode中为第三方库抑制这些Thread Sanitizer警告?
我正在使用线程清理程序运行boost 无锁队列文档中给出的 MPMC 示例,令我惊讶的是,这个基本示例包含按照 TSan 的数据竞争。知道可能出了什么问题吗?
OS: Red Hat Enterprise Linux Server release 7.7 / Ubuntu 18.04.4
Compiler: g++ (GCC) 9.3.1 20200408 (Red Hat 9.3.1-2) / g++ (Ubuntu 11.1.0-1ubuntu-18.04.1) 11.1.0
CPU Architecture: x86_64
Boost Version: 1.79
Run Code Online (Sandbox Code Playgroud)
TSan 的输出如下:
@vishal: g++ testQ.cpp -lboost_thread -L /usr/local/lib/ -pthread -fsanitize=thread -ggdb3 -fPIE -pie
@vishal: TSAN_OPTIONS="history_size=7" ./a.out
boost::lockfree::queue is lockfree
==================
WARNING: ThreadSanitizer: data race (pid=22019)
Atomic write of size 8 at 0x7b1000001c00 by thread T1:
#0 __tsan_atomic64_store <null> (libtsan.so.0+0x800ca)
#1 std::atomic<boost::lockfree::detail::tagged_ptr<boost::lockfree::queue<int>::node> >::store(boost::lockfree::detail::tagged_ptr<boost::lockfree::queue<int>::node>, …Run Code Online (Sandbox Code Playgroud) 有没有人尝试使用英特尔线程构建模块(TBB)来测试clang的ThreadSanitizer?
到目前为止,我的经验是,即使是相对简单的示例,您也会收到很多警告。不幸的是,其中许多似乎都是误报。
在另一个ThreadSanitizer问题的答案中,建议使用抑制文件。能帮上忙吗?是否有用于TBB或其他任何技术的禁止文件?
(附带说明:使用Helgrind时,它看起来很相似。许多误报。)
gcc v4.8.x添加用于调试程序的选项:
-fsanitize =螺纹
启用ThreadSanitizer,一种快速数据竞争检测器.将检测内存访问指令以检测数据争用错误.有关详细信息,请参阅http://code.google.com/p/data-race-test/wiki/ThreadSanitizer.
我在Fedora 19上的gcc版本:
gcc version 4.8.1 20130603 (Red Hat 4.8.1-1) (GCC)
Run Code Online (Sandbox Code Playgroud)
用以下命令链接我的程序(CMake的输出):
Linking C executable bin/ftu
/usr/bin/cmake -E cmake_link_script CMakeFiles/ftu.dir/link.txt --verbose=1
/usr/bin/cc -g -g -O0 -Wall -D_REENTRANT -rdynamic -fsanitize=thread -fPIE -pie CMakeFiles/ftu.dir/src/main/main.c.o -o bin/ftu -L/home/hl/ftu/arm/src/libapp/pc -rdynamic ../libapp/pc/libbase.a ../libapp/pc/libstbl.a ../libapp/pc/libstbl_utest.a ../libapp/pc/libbase_utest.a ../libapp/pc/libmem_utest.a ../libapp/pc/libmemspy_utest.a ../libapp/pc/libos_utest.a ../libapp/pc/libmain_utest.a ../libapp/pc/liblog_utest.a ../libapp/pc/libini_utest.a ../libapp/pc/libdsp_utest.a ../libapp/pc/libmstation_utest.a ../libapp/pc/libflist_utest.a ../libapp/pc/libdc_utest.a ../libapp/pc/libflist.a ../libapp/pc/libdsp.a ../libapp/pc/liblog.a ../libapp/pc/libini.a ../libapp/pc/libmstation.a ../libapp/pc/libdc.a ../libapp/pc/libmemspy.a ../libapp/pc/libmem.a ../libapp/pc/libos.a ../libapp/pc/libbase.a -lrt -lpopt -lpthread -Wl,-rpath,/home/hl/ftu/arm/src/libapp/pc
/usr/bin/ld: cannot find -ltsan
collect2: error: ld returned 1 exit …Run Code Online (Sandbox Code Playgroud) 考虑以下示例:
#include <iostream>
int main () {
int i = 0;
#pragma omp parallel
{
#pragma omp critical
{
++i;
}
}
std::cout << i;
}
Run Code Online (Sandbox Code Playgroud)
编译g++ -fopenmp -fsanitize=thread并运行收益
警告:ThreadSanitizer:数据竞争(pid = 9576)
通过线程T1在0x7ffdc170f600处读取大小4:
#0 main._omp_fn.0(a.out + 0x000000400d20)
#1 gomp_thread_start /build/gcc/src/gcc-5.2.0 /libgomp/team.c:118(libgomp.so.1 + 0x00000000f42d)先前通过线程T2在0x7ffdc170f600大小为4的写入:
#0 main._omp_fn.0(a.out + 0x000000400d35)
#1 gomp_thread_start /build/gcc/src/gcc-5.2.0/libgomp/team.c:118(libgomp .so.1 + 0x00000000f42d)位置是主线程的堆栈。
主线程在以下位置创建线程T1(tid = 9578,正在运行):
#0 pthread_create /build/gcc/src/gcc-5.2.0/libsanitizer/tsan/tsan_interceptors.cc:895(libtsan.so.0 + 0x000000027a37)
# 1 gomp_team_start /build/gcc/src/gcc-5.2.0/libgomp/team.c:796(libgomp.so.1 + 0x00000000f98f)
#2 __libc_start_main(libc.so.6 + 0x00000002060f)主线程在以下位置创建线程T2(tid = 9579,正在运行):
#0 pthread_create …
当使用带有 gcc 的消毒剂时,可以提供一个异常/抑制列表来处理误报等。
抑制文件格式记录不全。
每个抑制的形式都是
name_of_check:path_or_name
Run Code Online (Sandbox Code Playgroud)
的有效值是name_of_check什么?
gcc sanitizer thread-sanitizer address-sanitizer leak-sanitizer