75. Why does QueryPerformanceFrequency fail with error 998?
This happened to me a couple of weeks ago, and it was weird enough that I
thought I should write an article about it.
OK, let's say you need to do some metrics on a piece of code. "OK", you say
"all I have to do is haul out QueryPerformanceFrequency and
QueryPerformanceCounter, strut my funky 64 bit stuff, and I'll have all the
numbers I need" (yes, I really do talk like Huggy Bear, at least in my head,
anyway). So then you hack up the code, hit the compile key, fire up your
test harness, reach for your coffee cup and... Oh. Hang on. That's not
supposed to happen....
QueryPerformanceFrequency can fail, and it reports error 998
(ERROR_NOACCESS - Invalid access to memory location).
The reason for this is subtle, and took me an hour or so of rooting around to
discover. Like a great many people, I have to interface with other stuff, and
in order to do so I have to have my code byte-aligned : in my project settings,
the compiler is not set to the default 8 byte packing alignment, but 1 byte.
Before crowds of people warn me about the performance loss, yes, I do know
about this, I just have to do it, OK ? Everybody out there who has to deal with
microcontrollers is nodding their head right now, trust me.
The problem is that QueryPerformanceFrequency doesn't seem to cater for this
alignment oddity, and it cannot cope with accessing a variable which
isn't quadword aligned.
There are two solutions to this problem : either move your variable to a place
where you can guarantee it's quadword aligned (I moved mine to the beginning of
the class declaration), or use #pragma pack to force the relevant section of
your code to a pack setting of 8.