我有一些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问题对我来说更令人困惑,因为结构是按值传递的,所以返回的值作为副本自然会失去它的波动性?对于设定的情况,当数据被另一个过程改变时,波动性肯定更重要 - 我真的不知道写入数据位置时的易失性意味着什么。
注意:为了这个例子的目的,代码片段被删减了,那里有各种锁定和边界检查代码:)
答案 0 :(得分:0)
对于getIndexNode
,答案似乎相当简单:const_cast
在返回之前消除波动性,因为那是你想要的语义。请注意,只要volatile
指针指向的内存最初未声明为volatile
,就可以很好地定义它。
对于复制赋值运算符,您可以尝试将其设为volatile
,但是您还没有显示足够的代码来确定是否可以解决您的问题。例如index_node_t& index_node_t::operator=(const index_node_t&) volatile
。
答案 1 :(得分:0)
抛弃波动性永远不安全;您只能使用标记为volatile
的成员函数。
然而,这样做并不能保证安全;操作可能是非原子的,因此线程切换可以重新启动它们。您还必须确保通过某种锁定机制或其他方式,当您使用这些易失性结构之一时,操作将完成,而不会在操作期间通过其他内容更改结构的数据。
在共享内存中使用这些结构可能会更容易,但是使用一些可以通过OS函数原子读取和写入的bloc数据(如果存在这样的话)。