C++结构和挥发物

C++ structs and volatiles

本文关键字:挥发物 结构 C++      更新时间:2023-10-16

我有一些C代码,我希望向C++过渡,作为第一步,我正在尝试用C++编译器(现在是g++(编译。

它为IPC使用一些共享内存段,指向这些内存段的指针被声明为volatile:

volatile my_rec_t *myRec;

(其中my_rec_t只是一个普通的旧数据结构,myRec是作为这些结构的数组访问的(。

我对这个数据结构的波动性有一些问题:C++似乎比C需要更多的铸造,我不太确定我为什么。。。

有一些自动生成的访问器函数可以获取/设置共享内存结构中的字段(目前都是C样式代码(。这适用于基元数据类型,但如果my_rec_t中的一个字段本身是结构,则会产生错误:

int setIndexNode( int myRecNo, index_node_t indexNode )
{
  myRec[ myRecNo ].indexNode = indexNode;
  return TRUE;
}

在C++中,这会生成以下内容:error: passing 'volatile index_node_t' as 'this' argument of 'index_node_t& index_node_t::operator=(const index_node_t&)' discards qualifiers。为了获得价值:

index_node_t getIndexNode( int myRecNo )
{
  return myRec[ myRecNo ].indexNode;
}

错误为error: no matching function for call to 'index_node_t::index_node_t(volatile index_node_t&)'

get问题更让我困惑,因为结构是按值传递的,所以作为副本的返回值自然会失去它的波动性?对于既定的情况,在读取数据以防数据被另一个进程更改方面,波动性肯定更重要——我真的不知道在写入数据位置时波动性意味着什么。

注意:为了这个例子的目的,代码片段被削减了,其中有各种锁定和边界检查代码:(

对于getIndexNode,答案似乎相当简单:const_cast在返回波动性之前先消除波动性,因为这是您想要的语义。请注意,只要volatile指针所指向的内存最初不是声明为volatile的,那么将其丢弃就可以得到很好的定义。

对于副本分配运算符,您可以尝试将其设置为volatile,尽管您还没有显示足够的代码来确定这是否能解决您的问题。例如index_node_t& index_node_t::operator=(const index_node_t&) volatile

抛弃波动性永远都不安全;只能使用标记为volatile的成员函数。

然而,仅仅这样做并不能保证安全;这些操作可能是非原子的,因此线程开关可以重新激活它们。您还必须通过某种锁定机制或其他方式确保,当您使用这些易失性结构中的一个时,操作将完成,而结构的数据在操作过程中不会被其他东西更改。

事实证明,在共享内存中不使用这些结构,而是使用一些可以通过操作系统函数原子读取和写入的区块数据(如果存在这样的东西(可能会更容易。