2011-01-11 33 views
0

我有一個服務器,它使用全局變量來存儲下一個可用的唯一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_nextUniqueIdvoid*的值爲而不是等效值。 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_nextUniqueIdInterlockedIncrement64行爲將是正確的,它具有的值爲0,因爲初始值被寫入到錯誤的地址。

希望這是有道理的(問題描述,就是這樣)。

爲什麼g_nextUniqueId = 1 + lastId;行會寫入錯誤的地址?如果我將該類型更改回unsigned long,代碼將正常工作。

目前,唯一能解決的問題是將&g_nextUniqueId複製到void*,然後將其重新設置爲volatile unsigned __int64並進行賦值。

+0

這看起來很愚蠢,但我的第一個預感是你需要做一個完整的重新編譯。 – 2011-01-11 15:59:44

回答

2

聽起來像你需要做一個完整的重新編譯。

當您對多個翻譯單元中使用的類型進行更改時,通常會出現這種情況。有時候,依賴檢查器會感到困惑。