Visual Studio 2005 中的 volatile unsigned __int64 表现得很奇怪

发布于 2024-10-11 03:59:53 字数 1591 浏览 6 评论 0原文

我有一个服务器,它使用全局变量来存储下一个可用的唯一 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

余生一个溪 2024-10-18 03:59:53

听起来您需要进行完整的重新编译。

当您更改多个翻译单元中使用的类型时,通常会出现这种情况。有时依赖性检查器会感到困惑。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文