你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

关于 volalile陷阱的 分享和更正

[复制链接]
power568 发布时间:2019-10-31 10:33
       今天学习了 volatile 的陷阱,但是有些论坛上的东西都是有一个原版,然后之后的都是大家相互拷贝,拷贝归拷贝,至少得先理解原文的意思吧,或者写完后还是检查以下,虽然掉的东西很少,但是意思就差的很大了。原文这里就不拷贝了,这里说一下其中的错误之处:8 j' B+ `0 E, j; E& Q! ?& T$ @
   例:到底哪个volatile可能无效
; e' ^; @+ g4 }       就在你看过前面几个例子,感觉自己可能已经都弄明白了的时候,请看最后这个例子:
# G, r( t) l3 [( {

  1. , v. i" p7 M; c8 ^9 S
  2.   struct hw_bd { 5 c5 g# f8 ?( y5 j! O+ v$ u# Y, o1 @
  3.     ......;
    % f" u% ^# m4 K6 `+ s4 R  f
  4.     volatile unsigned char * volatile buffer;
    $ v( W% S/ w6 ]5 G: t+ S7 G: ]
  5.   };
    # j, I/ c9 j1 s2 x6 E. z9 r( u
  6.   
    - O% W2 _: _% {/ A8 O1 a* o( f
  7.   struct hw_bd *bdp; : h. q/ }8 }" H" W* y
  8.     Z0 ]  `) }, |# _8 c
  9.   ......; - x5 Y, d7 l" ]; A1 y9 {
  10.   bdp->buffer = ...; ① 4 k* |( v, i$ x) t. q0 O7 d5 {
  11.   bdp->buffer[i] = ...; ②  (错误的论坛是: bdp->buffer = ...; ② )
复制代码
  5 l8 D( j/ v4 I( U
  请问上面标记了①和②的两行代码,哪个是确实在访问volatile对象,而哪个又是undefined的结果?
9 k2 R; H% ~9 V1 a5 ^  J3 C7 a& m/ E& b  - R8 C1 Z$ i/ g: @, ^
  答案是:②是volatile的,①是undefined。来看本例的数据结构示意图:
4 [) y( d0 ^$ ]% Q  
5 k% g8 R4 ]8 m      (non-volatile), a; ]6 m$ W5 D! O1 k( F
  bdp -->+-------------+
5 T+ Q4 D3 }) \/ w/ i  {3 R5 E9 q      |       |
5 ]5 m/ G, @, [) }      |  ... ...  |
2 d' D3 o  y7 t- j( u# T      |       |
5 j+ L; k( @! e1 n# ~# z, u      +-------------+   (volatile)  7 V2 d) f- R. N3 w4 C
      |   buffer  |-->+------------+- d. r1 M; ?$ s% r) ^2 j- c
      +-------------+  |       |+ M4 i/ `; H0 V1 E  y" a) O
               |       |
) _0 ?; I6 U& }/ |( D               |       |
* X: b/ H+ U5 b" c               +------------+
/ Q  l. k6 a9 |4 K' A- ?2 Y               |  buffer |
/ F. r+ A0 a" Y/ m" I               +------------+
% b( w& w$ M) c& j4 E: r. L, e( \               |       |
2 U3 E* X0 Q+ }- \8 T3 l) D               |       |
: x9 m/ O3 z8 `* ^3 f               +------------+buffer成员本身是通过一个non-volatile的指针bdp访问的,按照C99标准的定义,这就属于undefined的情况,因此对bdp->buffer的访问编译器不一定能保证是volatile的;
) Z, l6 q. K) {7 f! _6 j4 W: ~% I  虽然buffer成员本身可能不是volatile的变量,但是buffer成员是一个指向volatile对象的指针。因此对buffer成员所指对象的访问编译器可以保证是volatile的,所以bdp->buffer是volatile的。 ( q- h- d' i3 ~
  
( h- n" H+ f& P5 a" C$ {4 x6 [  ~最后分享一下原文的链接(我认为的原为,这里仅作知识分享,如涉及到版权等问题,请告知,立即删除):  F& R9 b8 f$ r" f$ t0 \

0 L! I: U. z2 N5 w7 M) tvolatile的陷阱(栢图实验室)- w5 C! r* l. W, ~; E' g
或者5 N/ p2 W: G! F" s- v; g
volatile的陷阱(栢图实验室)
* s! E+ f. C; r6 e( R' t3 \/ U! H3 F# k+ U1 j
* y/ G# N9 h: o# u5 ~

# [$ u3 b& O$ s; d7 }' c6 d好记性不如烂笔头...
# {0 I) j2 [3 }0 N8 a7 X. F0 p+ e5 w) M. p+ u3 i
11.PNG
13.PNG
441.jpg
赞 收藏 评论4 发布时间:2019-10-31 10:33

举报

4个回答
子曰好人 回答时间:2019-10-31 11:02:07
楼主发的什么东西,表示没看懂,你那两句代码完全一样
power568 回答时间:2019-12-20 17:58:18
子曰好人 发表于 2019-10-31 11:02/ U# v, N4 ]/ N7 x9 u
楼主发的什么东西,表示没看懂,你那两句代码完全一样

0 g5 e4 M5 i& M' o多谢!应该是这样的8 _8 v+ ]2 i3 ]
  1. 6 m/ @2 D% ], p6 o! P
  2.   bdp->buffer = ...; ① 3 J, ^- c/ P: {" o( }
  3.   bdp->buffer[i] = ...; ②  (错误的论坛是: bdp->buffer = ...; ② )
复制代码
edmundlee 回答时间:2019-12-21 10:21:42
没验证过, 也没查过C99是否有如此规定, 假若是, 这就有些不合理, 甚至可以说个bug。
7 H- J4 k9 p$ J$ k结构体的指针因为不是volatile, 所以所有成员就是定义了volatile也没用, 那又何必把成员定义为volatile呢, 就是说要不就整个结构体都是volatile, 要不就都不是volatile。0 N2 s" f; P' D. H& }! O
再者 volatile unsigned char * volatile buffer; 这一句的意思是, 指针是volatile, 指针所指向的内容也是volatile& m( o& q) G3 h1 E7 y& b
要知道加volatile本身如非必要就是个额外的损耗。
7 I( r- m  y* i5 g; I& H要是定义另一 unsigned char *buf  = bdp->buffer;
" k# A1 a  i3 Q6 ?5 o6 qbuf[0]=xx;8 P) d1 F9 ^! ]- A, I$ I8 @0 W
结果是undefin才是合理的* G- x4 s3 P( C7 z
但因为结构体指针不是volatile而影响到成员就不合理了
' a2 r1 N" V: q0 y  \1 S# y

点评

volatile肯定会额外增加消耗的。 但是结构体的指针因为不是volatile, 所以所有成员就是定义了volatile也没用,确实有些不合理  发表于 2019-12-27 09:57
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版