I have a server, which uses a global variable to store the next available unique ID.
Originally, this was defined as unsigned long g_nextUniqueId volatile;
I'm changing all IDs to be 64-bit integers, so this line was changed to unsigned __int64 g_nextUniqueId volatile;
There are only two pieces of code that directly access this variable.
The first is to populate it when the server starts, it's very simple, it just runs a SQL query, retrieves a value and stores it into a unsigned __int64 lastId
, and then there's a statement to store it in the global, g_nextUniqueId = 1 + lastId;
.
The other is a function to retrieve and consume the next available ID. This is a one line function, return (unsigned __int64)InterlockedIncrement64((LONGLONG*)&g_nextUniqueId);
The problem seems to be there there are two different g_nextUniqueId
variables, for lack of better terms, in the initialization function.
When g_nextUniqueId
is populated, the correct value is written to the wrong address. According to the debugger, &g_nextUniqueId
is not the address the value was written to. If I store &g_nextUniqueId
in another variable, as a void*
, the values of &g_nextUniqueId
and the void*
are not equivalent. The void*
value is actually the correct address. This only holds true inside this one function; in any other function, the void*
and &g_nextUniqueId
are equivalent.
void* somePtr = (void*)&g_nextUniqueId;
Output(ToString(somePtr) + " " + ToString(&g_nextUniqueId));
// Output will be something "0x01BAF1D8 0x0012EFA4"
// 0x0012EFA4 is on or near the bottom of the stack, I believe.
Later, when I go to retrieve the next available ID, the g_nextUniqueId
the InterlockedIncrement64
acts upon will be the correct one, which has a value of 0, since the initial value was written to the wrong address.
Hopefully this makes sense (the problem description, that is).
Why is the g_nextUniqueId = 1 + lastId;
line writing to the wrong address? If I change the type back to unsigned long
, the code works correctly.
At the moment, the only solution I can come up with is copying &g_nextUniqueId
to a void*
and then casting it back to a volatile unsigned __int64
and assigning.
Sounds like you need to do a full recompile.
This is often the case when you make a change to a type used in multiple translation units. Sometimes the dependency checker gets confused.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.