Clang的线程安全分析静态工具
本文内容来自 Thread Safety Analysis,如需完整学习,请参考相关链接。
Clang线程安全分析工具是C++语言的一种扩展,用于警告代码中潜在的竞争条件。它在编译期间进行静态分析,无运行期性能损耗。即使该工具仍处在开发阶段,但已足够成熟,适合部署在生产环境上。
它的工作原理类似于一个针对多线程编程的类型系统。例如,变量 foo可被多线程访问,当分析工具检测到该变量在读写时没有被对应的锁所保护时,会提示一个警告。
基本概念
clang的线程安全分析工具使用capabilities来保护资源。这里的资源指的是成员数据,或者是提供访问底层资源的函数或方法。它能确保调用线程只有先拥有capability,才能访问对应资源。
假如 mu 代表一个 mutex ,当线程执行 mu.Lock() 后,代表它获得了访问 mu 所保护资源的 capability ,当它调用 mu.unLock() 后,代表它释放了该 capability。该线程拥有的capability是不可拷贝的,也不能销毁它,它只能释放该capability,以便其他线程获得该capability。
使用方法
线程安全分析工具使用属性注解来声明依赖,这些属性注解是附加在类、方法、数据成员之上的。官方推荐使用宏(mutex.h)来使属性注解可读性更好、可理解。
运行方法很简单,执行
clang -c -Wthread-safety example.cpp
适用于变量的注解
GUARDED_BY: 该属性声明,线程在对该变量进行读写之前,一定要获得对应的锁,以确保对该变量的操作是线程安全的。
PT_GUARDED_BY: 和GUARDED_BY类似,它用于指针和智能指针上,对指针自身没有约束,但对它所指向的数据施加属性保护。
Mutex mu;
int *p1 GUARDED_BY(mu);
int *p2 PT_GUARDED_BY(mu);
unique_ptr<int> p3 PT_GUARDED_BY(mu);
void test() {
p1 = 0; // Warning!
*p2 = 42; // Warning!
p2 = new int; // OK.
*p3 = 42; // Warning!
p3.reset(new int); // OK.
}
适用于函数的注解
REQUIRES(mu) 指示调用线程在调用该函数前,必须先获得mu锁。它假设调用者在调用该函数前,已经拥有mu锁,内部对共享变量的修改无需额外加锁。
REQUIRES_SHARED(), 与 REQUIRES 类似,但仅要求共享读访问权限。
Mutex mu1, mu2;
int a GUARDED_BY(mu1);
int b GUARDED_BY(mu2);
void foo() REQUIRES(mu1, mu2) {
a = 0;
b = 0;
}
void test() {
mu1.Lock();
foo(); // Warning! Requires mu2.
mu1.Unlock();
}
- ACQUIRE() 声明要求函数内部获得锁,直到退出该函数也无需释放它。调用者在调用该函数前,不能持有该锁。
- RELEASE() 声明函数具备释放锁的能力,调用者在调用入口处无需持有该锁,函数退出前会主动释放该锁。
Mutex mu;
MyClass myObject GUARDED_BY(mu);
void lockAndInit() ACQUIRE(mu) {
mu.Lock();
myObject.init();
}
void cleanupAndUnlock() RELEASE(mu) {
myObject.cleanup();
} // Warning! Need to unlock mu.
void test() {
lockAndInit();
myObject.doSomething();
cleanupAndUnlock();
myObject.doSomething(); // Warning, mu is not locked.
}
如果没有参数传递给 ACQUIRE 或 RELEASE,则假定入参为 this ,分析工具不会检查函数内部实现。常用在隐藏抽象接口的内部锁的实现细节。
- EXCLUDES(...) 声明调用者不能持有给定
capabilities, 该注解用来预防死锁,对于不可重入的锁,当同一个函数重入时,会获得2次锁,造成死锁。
Mutex mu;
int a GUARDED_BY(mu);
void clear() EXCLUDES(mu) {
mu.Lock();
a = 0;
mu.Unlock();
}
void reset() {
mu.Lock();
clear(); // Warning! Caller cannot hold 'mu'.
mu.Unlock();
}
- NO_THREAD_SAFETY_ANALYSIS: 关闭线程安全检查,该属性不属于声明的一部分,使用时要放在 .cpp 文件中。
适用于类的注解
CAPABILITY(): 指明该类的实例可被用作
capaility,string参数用来表明该capaility的种类,在警告时会输出。SCOPED_CAPABILITY:指明该类用于RAII风格的资源管理。
Clang的线程安全分析静态工具的更多相关文章
- clang的线程安全分析模块 thread safety analysis
介绍 Clang的线程安全分析模块是C++语言的一个扩展,能对代码中潜在的竞争条件进行警告.这种分析是完全静态的(即编译时进行),没有运行时的消耗.当前这个功能还在开发中,但它已经具备了足够的成熟度, ...
- java线程dump分析工具
jstack和线程dump分析 java程序性能分析之thread dump和heap dump 一.[内存dump] jmap –dump:live,format=b,file=heap.bin ...
- 【转】java线上程序排错经验2 - 线程堆栈分析
前言 在线上的程序中,我们可能经常会碰到程序卡死或者执行很慢的情况,这时候我们希望知道是代码哪里的问题,我们或许迫切希望得到代码运行到哪里了,是哪一步很慢,是否是进入了死循环,或者是否哪一段代码有问题 ...
- Linux性能分析命令工具汇总
转自:http://rdc.hundsun.com/portal/article/731.html?ref=myread 出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望,因此整理了这篇文章. ...
- (转)java线程安全问题之静态变量、实例变量、局部变量
java多线程编程中,存在很多线程安全问题,至于什么是线程安全呢,给出一个通俗易懂的概念还是蛮难的,如同<java并发编程实践>中所说: 写道 给线程安全下定义比较困难.存在很多种定义,如 ...
- Spring中获取request的几种方法,及其线程安全性分析
前言 本文将介绍在Spring MVC开发的web系统中,获取request对象的几种方法,并讨论其线程安全性. 原创不易,如果觉得文章对你有帮助,欢迎点赞.评论.文章有疏漏之处,欢迎批评指正. 欢迎 ...
- [No000016E]Spring 中获取 request 的几种方法,及其线程安全性分析
前言 本文将介绍在Spring MVC开发的web系统中,获取request对象的几种方法,并讨论其线程安全性. 原创不易,如果觉得文章对你有帮助,欢迎点赞.评论.文章有疏漏之处,欢迎批评指正. 欢迎 ...
- java线程安全问题之静态变量、实例变量、局部变量
java多线程编程中,存在很多线程安全问题,至于什么是线程安全呢,给出一个通俗易懂的概念还是蛮难的,如同<java并发编程实践>中所说: 写道 给线程安全下定义比较困难.存在很多种定义,如 ...
- Spring中获取request的几种方法,及其线程安全性分析(山东数漫江湖)
前言 本文将介绍在Spring MVC开发的web系统中,获取request对象的几种方法,并讨论其线程安全性. 原创不易,如果觉得文章对你有帮助,欢迎点赞.评论.文章有疏漏之处,欢迎批评指正. 欢迎 ...
随机推荐
- Pthon魔术方法(Magic Methods)-上下文管理
Pthon魔术方法(Magic Methods)-上下文管理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.上下文管理方法 __enter__: 进入与此对象相关的上下文.如果 ...
- 泛微 e-cology OA 远程代码执行漏洞复现
0x00 前言 Poc已在github公开,由于环境搭建较为复杂,所以我在空间搜索引擎中找了国外的网站进行复现 如果有想自行搭建环境复现的可以在公众号内回复“泛微环境”即可获取源码及搭建方式 0x01 ...
- jquery选择器之全选择器
在CSS中,经常会在第一行写下这样一段样式 * {padding: 0; margin: 0;} 通配符*意味着给所有的元素设置默认的边距.jQuery中我们也可以通过传递*选择器来选中文档页面中的元 ...
- Cisco网络模拟器踩坑记录
1.在我们新建一个拓扑图的时候,选择设备之间的连线种类有时会导致线路不通的情况(两个端口上为红色点)这时候建议拆除这条线后选择闪电标记 的万能线帮助我们自动创建连线(这时就能根据它显示的线条种类得知应 ...
- SOA 架构与微服务架构的区别
注重重用,微服务注重重写 SOA 的主要目的是为了企业各个系统更加容易地融合在一起. 微服务通常由重写一个模块开始.要把整个巨石型的应用重写是有很大的风险的,也不一定必要.我们向微服务迁移的时候通常从 ...
- PHP隐藏IP地址末位的方法
很久之前写过一个使用ASP隐藏IP地址末位的文章,也就是有时候为了保护用户的隐私,会隐藏用户的IP地址,达成类似于 222.222.222.* 的效果. 现在想要用PHP来实现,经过尝试,其实非常简 ...
- CSE301 – Bio-Computation
CSE301 – Bio-Computation Assessment 3Contribution to overall module assessment 10%Submission deadlin ...
- C++中继承 声明基类析构函数为虚函数作用,单继承和多继承关系的内存分布
1,基类析构函数不为虚函数 #include "pch.h" #include <iostream> class CBase { public: CBase() { m ...
- shell脚本编程基础之case语句
基础简介 脚本编程分为: 面向过程 选择结构:if语句,单分支.双分支.多分支:case语句 控制结构:顺序结构(默认) 循环结构:for.while.until 面向对象 case语句结构 case ...
- Connection to newtaotao failed. [08001] Could not create connection to database
jdbc.url=jdbc:mysql://localhost:3306/newtaotao?serverTimezone=UTC&characterEncoding=utf-8 数据库是5. ...