C++代码中与易失性相关的错误

Volatile related error in C++ code

本文关键字:错误 易失性 代码 C++      更新时间:2023-10-16

你能帮我理解为什么编译器给我这些错误消息吗?我相信挥发性物体的成员也是易变的。我指的是从这里开始的。但它表明,如果我们有一个结构:

struct someStruct
{
    int d;
};

而"p"的定义如下:

volatile someStruct* volatile* p;

&(*p)->d具有以下类型"int* volatile*"而不是"volatile int* volatile*"。下面是我正在处理的实际代码。


这些行(标有错误 1 和 2)是编译器抛出错误消息的地方:

#include <vector>
#include <windows.h>
using namespace std;
struct ThreadInfo
{
    bool bWaiting = false;
    bool bWorking = false;
};
struct lThreadInfo
{
    ThreadInfo d;
    lThreadInfo *pNextList = nullptr;
} volatile *volatile lThreads(nullptr);
thread_local ThreadInfo* currentThr(nullptr);
void CreateThread_(void (*pFunc)(ThreadInfo*))
{
    volatile lThreadInfo* volatile* p = &lThreads;
    for(; *p; p = &(*p)->pNextList); //**//error 1!**
    *p = new lThreadInfo;
    CreateThread(
            nullptr,                   // default security attributes
            0,                      // use default stack size
            (long unsigned int (*)(void*))pFunc,       // thread function name
            &(*p)->d,          // argument to thread function     **//error 2!**
            0,                      // use default creation flags
            nullptr);
}

错误消息如下:

error 1: invalid conversion from 'lThreadInfo* volatile*' to 'volatile lThreadInfo* volatile*' [-fpermissive]
error 2: invalid conversion from 'volatile void*' to 'LPVOID {aka void*}' [-fpermissive]

注意:我知道易失性与线程安全无关,所以不要费心告诉我。注意1:我在Windows上使用mingw64编译器。

pNextList通过

volatile访问路径也是volatile。但pNextList指针尖头类型具有与以前相同的CV资格。

也就是说,对于

struct A
{
    lThreadInfo* p;
};
someStruct volatile* volatile* p;
  • *p 是类型 someStruct volatile* volatile 的左值
  • (*p)->dlThreadInfo* volatile 类型的左值。

因此,在(*p)->d类型中,您错过了lThreadInfo*之间的波动性。[expr.ref]/4:

如果E2是非静态数据成员,并且E1的类型为"cq1 vq1 X",E2的类型为"cq2 vq2 T",表达式 指定由第一个指定的对象的命名成员 表达。如果E1是左值,则E1.E2是左值;如果E1 是一个 x值,那么E1.E2是一个 x值;否则,它是一个 prvalue。 让符号 vq12 代表 vq1 和 vq2 的"联合";也就是说,如果 vq1 或vq2 volatile ,则VQ12volatile .同样,让符号 cq12 代表 cq1 和 cq2 的"联合";也就是说,如果 CQ1 或 CQ2 const,则 cq12 const 。如果E2被声明为可变 成员,则E1.E2的类型为"VQ12 T"。如果E2不是 声明为可变成员,则E1.E2类型为"CQ12VQ12 T"。

vq1 volatilevq2 为空。因此 vq12volatile 。因此表达式的类型是 volatile T ,即 lThreadInfo* volatile