Unstable related error in C ++ code

Can you help me understand why the compiler gives me these error messages? I believe that members of volatile objects are also unstable. I mean here . But this shows that if we have a structure:

struct someStruct { int d; }; 

And 'p' is defined as follows:

 volatile someStruct* volatile* p; 

&(*p)->d have the following type 'int * volatile *' instead of 'volatile int * volatile *'. Below is the actual code I'm working on.


Lines (tagged with error 1 and 2) is where the compiler generates error messages:

 #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); } 

The error messages are as follows:

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

Note I know that volatility has nothing to do with thread safety, so I don’t need to say that. Note 1 . I am using the mingw64 compiler for Windows.

+5
source share
1 answer

pNextList , via the volatile access path, is also volatile . But pNextList is a pointer . The pointee type has the same cv qualification as before.

That is, for

 struct A { lThreadInfo* p; }; someStruct volatile* volatile* p; 
  • *p is a value of type someStruct volatile* volatile
  • (*p)->d is a value of type lThreadInfo* volatile .

So, in type (*p)->d you lack the variability between lThreadInfo and * . [Expr.ref] / 4:

If E2 is a non-static data element and type E1 is β€œcq1 vq1 X ” and type E2 is β€œcq2 vq2 T ”, the expression denotes the named element of the object, indicated by the first expression. If E1 is the value of l, then E1.E2 is an lvalue; if E1 is the value of x, then E1.E2 is the value of x; otherwise, this value. Let the notation vq12 mean the β€œunion” of vq1 and vq2; those. if vq1 or vq2 is volatile , then vq12 is volatile . Similarly, let the notation cq12 denote the β€œunion” of cq1 and cq2; that is, if cq1 or cq2 is const , then cq12 is const . If E2 declared a mutable member, then the type of E1.E2 is "vq12 T ". If E2 not declared as a mutable member, then the type of E1.E2 is "cq12 vq12 T " .

vq1 is volatile , and vq2 is empty. So vq12 is volatile . Thus, the type of the expression is volatile T , which is lThreadInfo* volatile .

+2
source

Source: https://habr.com/ru/post/1206959/


All Articles