Microsoft has been nice enough to supply us with many typedefs that we can use when writing code that should simplify development, especially when our code may be used to target different Microsoft OSs. On the other hand, these typedefs can also cause problems for us when using them to write device drivers. The typedefs that can cause problems are the ones that are pointers, like PBYTE, PDWORD… The reason that they can cause problems is that modifiers like volatile don’t modify in the way that we need them to modify our definitions.
Looking at windef.h we can see how PDWORD is defined:
typedef DWORD near          *PDWORD;
If we use this in our code to define a pointer to a 32 bit register:
PDWORD MyReg;
We get a pointer to a DWORD, or 32 bit data. The problem comes when we use this in code that can be optimized by the compiler:
*MyReg = 0x1;
while( *MyReg & 0x1 );
 
This while loop should read from the data pointed to by MyReg, and continue looping until bit 0 is cleared. But the compiler thinks that it is smarter than we are, so it sees that *MyReg has bit 1 set, and will change the loop to a while( FOREVER ); which is not equal to the code that we thought that we wrote. The obvious solution is to use volatile in the definition and since we know that:
volatile DWORD *MyReg;
Would solve the problem because it defines a static pointer to volatile data, the assumption that may programmers make is that:
volatile PDWORD MyReg;
Is an equivalent definition. It is not an equivalent definition; it defines a volatile pointer to static data.   The easy solution is to use the previous definition that we know will work to keep the optimizer from breaking our code.
I have lost too much time debugging code that I receive from others that use the P* typedefs. So, I always go through code from others and change the definitions to remove the ‘P’. The last time that I found a problem in with the P* typedefs, the definitions were hidden away in a header file in a different folder, so it wasn’t so obvious. We only found the cause when we reviewed the COD files that the compiler output, and could see that our carefully developed code was being optimized out.
Copyright © 2008 – Bruce Eitman
All Rights Reserved