简体   繁体   中英

volatile unsigned __int64 with Visual Studio 2005 behaves strangely

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM