CON52-CPP. 在多线程访问位域时避免数据竞争
原文链接:
CON52-CPP. Prevent data races when accessing bit-fields from multiple threads
当访问位域时,线程可能会无意中访问相邻内存中的另一个位域。这是因为编译器在合适的情况下会将多个相邻位域存储于一个存储单元中。因此,数据竞争可能不仅存在于被多个线程访问的位域中,也可能存在于共享同一个字节或字的其他位域中。此问题难以诊断,因为多个线程同时修改同一内存区域可能不易被察觉。
在并发编程中,一种防止数据竞争的方法是使用互斥量。当所有线程都遵循互斥量规则,互斥量可以提供对共享对象安全可靠的访问。然而,当互斥量不受访问线程控制时,互斥量对其他可能被访问的对象不提供保证。不幸的是,还没有可移植的方法可以区分哪些相邻位域可能会和期望位域存储在一起。
另一种方法是在任意两个位域之间插入一个非位域成员,以确保每个位域都是其存储单元中唯一被访问的。这种技术有效地保证了没有两个位域会同时被访问。
不合规代码示例(位域)
相邻的位域可能存储在一个内存位置中。因此,在不同线程中修改相邻位域是未定义行为,如此非符合代码示例所示:
1 | struct MultiThreadedFlags { |
例如,可能存在以下指令序列:
1
2
3
4
5
6
7
8 Thread 1: register 0 = flags
Thread 1: register 0 &= ~mask(flag1)
Thread 2: register 0 = flags
Thread 2: register 0 &= ~mask(flag2)
Thread 1: register 0 |= 1 << shift(flag1)
Thread 1: flags = register 0
Thread 2: register 0 |= 2 << shift(flag2)
Thread 2: flags = register 0
合规解决方案(位域,C++11及以上版本,互斥量)
这个合规解决方案使用互斥量来保护所有对flags的访问,从而避免任何数据竞争。
1 |
|
合规解决方案(C++11)
在这个符合解决方案中,两个线程同时修改一个结构体的两个不同的非位域成员。由于这些成员在内存中占据不同的字节,因此不需要并发保护。
1 | struct MultiThreadedFlags { |
与标准的早期版本不同,C++11及其后续版本明确定义了一个内存位置,并在[intro.memory]段落4 [ISO/IEC 14882-2014]中提供以下说明:
[注释:因此,位域和相邻的非位域位于不同的内存位置,因此可以通过两个执行线程并发更新而不会产生干扰。如果一个位域声明在嵌套的结构体申明中而另一个位域不是,或者两个位域被一个零长度位域声明或非位域声明分隔开,同样适用。如果同一个结构体中的两个位域之间的所有字段都是非零宽度的位域,那么并发地更新它们是不安全的。 - 结束注释]
Risk Assessment
Although the race window is narrow, an assignment or an expression can evaluate improperly because of misinterpreted data resulting in a corrupted running state or unintended information disclosure.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
CON52-CPP | Medium | Probable | Medium | P8 | L2 |
Automated Detection
Tool | Version | Checker | Description |
---|---|---|---|
Astrée | 22.10 | **read_write_data_race write_write_data_race ** | Supported |
Axivion Bauhaus Suite | 7.2.0 | CertC++-CON52 | |
CodeSonar | 7.3p0 | CONCURRENCY.DATARACE | Data Race |
Coverity | 6.5 | RACE_CONDITION | Fully implemented |
Helix QAC | 2023.1 | C++1774, C++1775 | |
Parasoft C/C++test | 2022.2 | CERT_CPP-CON52-a | Use locks to prevent race conditions when modifying bit fields |
Polyspace Bug Finder | R2023a | CERT C++: CON52-CPP | Checks for data races (rule partially covered) |
PRQA QA-C++ | 4.4 | 1774, 1775 | Enforced by MTA |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
SEI CERT C Coding Standard | CON32-C. Prevent data races when accessing bit-fields from multiple threads |
---|---|
Bibliography
[ISO/IEC 14882-2014] | Subclause 1.7, “The C++ memory model” |
---|---|
本文标题:CON52-CPP. 在多线程访问位域时避免数据竞争
文章作者:xwnb
发布时间:2023-04-01
最后更新:2023-04-17
原始链接:https://xwnb.github.io/posts/3975169340/
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!并保留本声明。感谢您的阅读和支持!
分享