Visual Studio 2005 中的 volatile unsigned __int64 表现得很奇怪
我有一个服务器,它使用全局变量来存储下一个可用的唯一 ID。
最初,它被定义为 unsigned long g_nextUniqueId volatile;
我将所有 ID 更改为 64 位整数,因此这一行更改为 unsigned __int64 g_nextUniqueId volatile;
这里只有两段代码直接访问这个变量。
第一个是在服务器启动时填充它,这很简单,它只是运行一个 SQL 查询,检索一个值并将其存储到一个 unsigned __int64 lastId
中,然后有一个语句将其存储在全局,g_nextUniqueId = 1 + lastId;
。
另一个是检索和使用下一个可用 ID 的函数。这是一个单行函数, return (unsigned __int64)InterlockedIncrement64((LONGLONG*)&g_nextUniqueId);
问题似乎是有两个不同的 g_nextUniqueId
变量,由于缺乏更好的术语,在初始化函数中。
当填充g_nextUniqueId
时,正确的值被写入错误的地址。根据调试器的说法,&g_nextUniqueId
不是值写入的地址。如果我将 &g_nextUniqueId
作为 void*
存储在另一个变量中,则 &g_nextUniqueId
的值和 void*< /code> 不等效。
void*
值实际上是正确的地址。这只适用于这一个函数;在任何其他函数中,void*
和 &g_nextUniqueId
是等效的。
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.
稍后,当我去检索下一个可用 ID 时,InterlockedIncrement64
所作用的 g_nextUniqueId
将是正确的 ID,其值为 0,因为初始值为写入错误的地址。
希望这是有道理的(即问题描述)。
为什么 g_nextUniqueId = 1 + lastId;
行写入了错误的地址?如果我将类型更改回 unsigned long
,代码将正常工作。
目前,我能想到的唯一解决方案是将 &g_nextUniqueId
复制到 void*
,然后将其转换回 易失性无符号 __int64
代码>并分配。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
听起来您需要进行完整的重新编译。
当您更改多个翻译单元中使用的类型时,通常会出现这种情况。有时依赖性检查器会感到困惑。
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.