Volatile关键字允许访问UnitTest++中的常量结构
Volatile keyword allows access to const structures in UnitTest++
我正在使用UnitTest++框架对我负责的一些C代码进行单元测试。最终产品是嵌入式的,并使用const结构来保存配置信息。由于目标主机可以异步修改配置,因此结构的成员都是易失性的。一些结构也被宣布为易失性结构。
当我使用const_cast试图修改UnitTest Windows 7主机上缺少volatile关键字的结构实例时,我会遇到分段错误。这对我来说是有道理的。但是,如果结构实例是用volatile关键字声明的,那么测试就通过了。这对我来说没有意义。
下面是一个快速代码示例,显示了Win7上的gcc问题。切换define值会导致segfault出现与否,这取决于是否使用了结构的volatile实例。
typedef struct
{
volatile int foo;
volatile int bar;
} TestStruct;
const TestStruct constStruct = { 1, 2};
volatile const TestStruct volatileConstStruct = { 3, 4};
#define SEG_FAULT 0
int main(void)
{
TestStruct * constPtr = const_cast<TestStruct*>(&constStruct);
TestStruct * constVolPtr = const_cast<TestStruct*>(&volatileConstStruct);
#if(SEG_FAULT == 0)
constVolPtr->foo = 10;
#else
constPtr->foo = 20;
#endif
}
有人能帮我理解为什么volatile关键字为segfault提供了一个变通方法吗?此外,有人能提出一种方法,允许我修改结构中的值进行单元测试,而不向所有结构实例添加volatile关键字吗?
编辑:
我刚刚发现你可以在C:中做到这一点
#define const
在测试夹具中包含上面有效的"const undefine"可以让我的目标编译器看到const关键字,并将结构正确地放入闪存中。然而,UnitTest++编译器上的预处理器去掉了const关键字,所以我的测试夹具能够修改结构。
这个解决方案的缺点是,我不能添加单元测试来验证函数调用的正确const操作。然而,由于从结构实例中删除常量不是一个选项(需要将数据放在闪存中),这似乎是我不得不面对的一个缺点。
为什么会有这种奇怪的行为
使用const_cast
修改const
对象是一种未定义的行为
当你有一个指向非常量对象的const
指针,并且你想把指针指向它时,就会使用const_cast
为什么它适用于volatile
不确定。然而,它仍然是一种未定义的行为,你只是幸运的是它有效。
Undefined Behavior的问题是,所有安全赌注都被取消,程序可能会显示任何行为。它可能看起来有效,也可能不起作用。可能会崩溃或表现出任何奇怪的行为
最好不要编写任何显示"未定义行为"的代码,这样可以为此类情况保存有保证的解释。
如何解决此问题
不要将修改的对象声明为const
,因为您打算在程序/测试过程中修改它们,所以它们不应该是const
。目前,你正在向编译器承诺你的结构对象是不可变的(const),但后来你通过修改它打破了这个约定。只有在你能遵守的情况下才能做出这个承诺。
我相信标准中的脚注会给出答案。(注意脚注不规范。)
在标准草案N1570的§6.7.3中:
132)该实现可以放置不易失的const对象在只读存储区域中。
这意味着用volatile
关键字定义的结构将被放置在读写存储器中,尽管它是定义为const
的。
有人可能会争辩说,编译器不允许将任何结构放在只读内存中,因为它们都包含易失性成员。如果我是你的话,我会寄一份编译器错误报告。
有人能帮我理解为什么volatile关键字显示segfault的解决方法?此外,有人能建议一种方法吗允许我修改结构中的值以进行单元测试将volatile关键字添加到所有结构实例?
你不能。一个const
对象被放在只读内存中,如果你对它进行写入,你会触发一个segfault。要么删除const
,要么添加volatile
——我强烈建议删除const
。
- #定义c-预处理器常量..我做错了什么
- 用C++中的一个变量定义一个常量
- 什么时候在C++中返回常量引用是个好主意
- 代理对象的常量正确性
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 通过多个头文件使用常量变量
- 在cuda线程之间共享大量常量数据
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 是默认情况下分配给char数组常量的值
- 私有类型的静态常量成员
- 类似枚举的计算常量
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 为什么我可以通过引用修改常量返回
- 如何创建长度由常量参数指定的数组
- 当一个值是非常量但用常量表达式初始化时使用constexpr
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- 隐式常量/非常量运算符布尔
- 非常量变量只读位置的赋值
- Volatile关键字允许访问UnitTest++中的常量结构