我有一个服务器,它使用一个全局变量来存储下一个可用的唯一 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*
不是等效的。 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 时,g_nextUniqueId
InterlockedIncrement64
actions on 将是正确的,其值为 0,因为初始值被写入了错误的地址。
希望这是有道理的(即问题描述)。
为什么是g_nextUniqueId = 1 + lastId;
行写入错误的地址?如果我将类型改回 unsigned long
, 代码工作正常。
目前,我能想出的唯一解决方案是复制 &g_nextUniqueId
到 void*
然后将其转换回 volatile unsigned __int64
和分配。
最佳答案
听起来您需要进行完全重新编译。
当您对多个翻译单元中使用的类型进行更改时,通常会出现这种情况。有时依赖性检查器会感到困惑。
关于c++ - 带有 Visual Studio 2005 的 volatile unsigned __int64 行为异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4659571/