我有一台服务器,它使用全局变量来存储下一个可用的唯一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
动作将是正确的,其值为0,因为初始值已写入错误的地址。
希望这有意义(问题描述,即)。
为什么g_nextUniqueId = 1 + lastId;
行写错了地址?如果我将类型更改回unsigned long
,则代码可以正常工作。
目前,我能提出的唯一解决方案是将&g_nextUniqueId
复制到void*
,然后将其转发回volatile unsigned __int64
并进行分配。
答案 0 :(得分:2)
听起来你需要完全重新编译。
当您对多个翻译单元中使用的类型进行更改时,通常会出现这种情况。有时依赖检查器会感到困惑。