位域结构体多线程访问出错的问题分析

  位域结构体能节省一些内存空间,但是使用不当会产生race conditions,导致程序异常,下面简要分析错误产生的原因和解决方案。

  首先定义一个简单的bit field结构体。

+struct bit_filed {

+       unsigned a : 1;

+       unsigned b : 1;

+       unsigned c : 1;

+       unsigned d : 1;

+       unsigned e : 1;

+       unsigned f : 1;

+       unsigned g : 1;

+       unsigned h : 1;

+} val;

+

+

+int test_bitfield1(void)

+{

+       val.a = 1;

+       return 0;

+}

+

+int test_bitfield2(void)

+{

+       val.b = 1;

+       return 0;

+}

  然后反汇编

ffffffc0005421e8 <test_bitfield1>:

ffffffc0005421e8:       f0000fa1        adrp    x1, ffffffc000739000 <__hyp_idmap_text_end+0x4800>

ffffffc0005421ec:       f9426821        ldr     x1, [x1,#1232]

ffffffc0005421f0:       52800000        mov     w0, #0x0                        // #0

ffffffc0005421f4:       39400022        ldrb    w2, [x1]

ffffffc0005421f8:       32000042        orr     w2, w2, #0x1

ffffffc0005421fc:       39000022        strb    w2, [x1]

ffffffc000542200:       d65f03c0        ret

ffffffc000542204 <test_bitfield2>:

ffffffc000542204:       f0000fa1        adrp    x1, ffffffc000739000 <__hyp_idmap_text_end+0x4800>

ffffffc000542208:       f9426821        ldr     x1, [x1,#1232]

ffffffc00054220c:       52800000        mov     w0, #0x0                        // #0

ffffffc000542210:       39400022        ldrb    w2, [x1]

ffffffc000542214:       321f0042        orr     w2, w2, #0x2

ffffffc000542218:       39000022        strb    w2, [x1]

ffffffc00054221c:       d65f03c0        ret

  可以看到,这种情况下最小访存单元是一个byte,在上面标黄的指令中会从内存读取一个副本,如果test_bitfield1在执行黄色指令后被test_bitfield2强行插入,test_bitfield2执行完毕后test_bitfield1继续执行,

在这种情况下test_bitfield2所做的修改会被丢弃。

  所以平时如果需要用到bit filed struct, 需要注意:

  1. 不同位域变量是不是在一个storage unit(可以通过反汇编查看)里面

  2. 有没有被并发访问的可能。

  下面这篇文章分析了这个问题并给出了几种解决方案:

  https://www.securecoding.cert.org/confluence/display/seccode/CON32-C.+Prevent+data+races+when+accessing+bit-fields+from+multiple+threads

  1. One approach for preventing data races in concurrent programming is to use a mutex
  2. Another approach is to insert a non-bit-field member between any two bit-fields to ensure that each bit-field is the only one accessed within its storage unit.
  3. Use distinct non-bit-field members of a structure
时间: 2024-10-08 03:28:19

位域结构体多线程访问出错的问题分析的相关文章

位域结构体简介

最近实习接触到一个新的知识点,C/C++的位域结构体. 以下开始摘抄自:here 位段(bit-field)是以位为单位来定义结构体(或联合体)中的成员变量所占的空间.含有位段的结构体(联合体)称为位段结构.采用位段结构既能够节省空间,又方便于操作. 位段的定义格式为: 1 type [var]: digits 其中type只能为int,unsigned int,signed int三种类型(int型能不能表示负数视编译器而定,比如VC中int就默认是signed int,能够表示负数).位段名

C语言之结构体以及结构体对齐访问

1:简单理解,结构体就是数组的进一步发展,数据的优点和缺陷在于数据里面是元素类型必须相同,但是结构体没有这个要求,结构体里面元素的类型可以相同也可以不同. 2:结构体的定义: struct student {     int age;     char name[20]; }s1; 上面这种方法是结构体定义的同时定义变量,结构体的定义有两部分组成 struct studen:结构体的类型 s1:类型为struct student的结构体变量,当然还可以用struct studet s2:l来定义

结构体中指针赋值问题的分析及C代码示例

问题描述 某结构体的定义如下: typedef struct { int iAge; // 年龄 char szAddr1[100]; // 地址1 char *pszAddr2; // 地址2 char **pszAddr3; // 地址3 } T_PeopleInfo; 请问如何对结构体中的各个成员变量(尤其是指针变量)进行赋值? 问题分析及C代码示例 我们可以看到,在结构体T_PeopleInfo中,pszAddr2和pszAddr3均为指针,其中pszAddr2为一级指针,pszAddr

结构体的对齐访问

什么是结构体对齐访问(1)结构体中元素的访问其实本质上还是用指针方式,结合这个元素在整个结构体中的偏移量和这个元素的类型来进行访问的.(2)但是实际上结构体的元素的偏移量比较复杂,因为结构体要考虑元素的对齐访问,所以每个元素时间占的字节数和自己本身的类型所占的字节数不一定完全一样.(譬如char c实际占字节数可能是1,也可以是2,也可能是3,也可以能4····)(3)一般来说,我们用.的方式来访问结构体元素时,我们是不用考虑结构体的元素对齐的.因为编译器会帮我们处理这个细节.但是因为C语言本身

C语言结构体的字节对齐原则

转载:http://blog.csdn.net/shenbin1430/article/details/4292463 为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐. 对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同.一些平台对某些特定类型的数据只能从某些特定地址

数组强制转换成结构体指针,结构体内部指针的指向问题

如果直接操作结构体成员是不会取到不期望的值 但是对于要求连续数据格式的时候需要考虑对齐的问题 例如通讯中的数据帧格式等 ,如 ip数据包等#pragma   pack(1) struct   tagStruct {     ... } t; #pragma   pack() 的方式来强制连续存放 其中前面   pack(1)   是指对齐边界为   1 1.几个结构体例子: struct{short a1;short a2;short a3;}A; struct{long a1;short a2

【转】C语言结构体的字节对齐原则

原文链接:http://blog.csdn.net/shenbin1430/article/details/4292463 为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐. 对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同.一些平台对某些特定类型的数据只能从某些特定

结构体指针

结构体与指针 1.结构体指针的数值为某个结构体的内存空间的地址,从而指针指向某个结构体. 2.结构体指针的初始值为空(0),不指向任何结构体. 3.malloc操作:创建一个新的内存空间(从内存中选择一个内存空间存储结构体),p指向这个结构体,p的值为这个结构体的内存空间的地址. 4.结构体指针的赋值:一个结构体指针的数值等于另外一个结构体指针的数值,从而两个结构体指针指向相同的结构体.当对某个结构体进行访问时,选择的结构体指针只要满足该结构体指针指向这个结构体即可,即可以有很多种选择. 5.当

黑马程序员-C学习日记-结构体

------- ios培训. android培训.java培训.期待与您交流! ---------- 一.局部变量与全局变量 1.局部变量:定义在函数内部的变量以及函数形参称为局部变量 作用域:从定义的那一行开始直到其所在的代码块结束 生命周期:从程序运行到定义那一行开始分配存储空间到程序离开该变量所在的作用域 特点:(1)相同作用域内不可以定义重名变量 (2)不同作用域可以定义重名变量,内部作用域变量可以覆盖外部作用域变量 2.全局变量:函数外部定义的变量 声明: 数据类型 变量名称 定义: