我有一個服務器,它使用全局變量來存儲下一個可用的唯一ID。使用Visual Studio 2005的volatile unsigned __int64行爲奇怪
原來,這個被定義爲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
並進行賦值。
這看起來很愚蠢,但我的第一個預感是你需要做一個完整的重新編譯。 – 2011-01-11 15:59:44