2011-01-11 16 views
0

Ich habe einen Server, der eine globale Variable verwendet, um die nächste verfügbare eindeutige ID zu speichern.flüchtige unsignierte __int64 mit Visual Studio 2005 verhält sich seltsam

Ursprünglich wurde dies als unsigned long g_nextUniqueId volatile; definiert ich alle IDs Ändern 64-Bit-Integer sein, so wurde diese Linie geändert unsigned __int64 g_nextUniqueId volatile;

Es gibt nur zwei Stücke von Code, der direkt auf diese Variable zugreifen.

Die erste ist, es zu füllen, wenn der Server gestartet wird, ist es sehr einfach, es läuft gerade eine SQL-Abfrage, ruft einen Wert und speichert sie in einem unsigned __int64 lastId, und dann gibt es eine Aussage zu speichern in der globalen, g_nextUniqueId = 1 + lastId;.

Die andere ist eine Funktion zum Abrufen und konsumieren der nächsten verfügbaren ID. Dies ist eine einzeilige Funktion, return (unsigned __int64)InterlockedIncrement64((LONGLONG*)&g_nextUniqueId);

Das Problem scheint dort zu sein gibt es zwei verschiedene g_nextUniqueId Variablen, aus Mangel an besseren Bedingungen, in der Initialisierungsfunktion.

Wenn g_nextUniqueId aufgefüllt ist, wird der korrekte Wert in die falsche Adresse geschrieben. Entsprechend dem Debugger ist &g_nextUniqueIdnicht die Adresse, zu der der Wert geschrieben wurde. Wenn ich &g_nextUniqueId in einer anderen Variablen als void* speichere, sind die Werte &g_nextUniqueId und void*nicht gleichwertig. Der void* Wert ist tatsächlich die richtige Adresse. Dies gilt nur innerhalb dieser einen Funktion; in jeder anderen Funktion sind die void* und &g_nextUniqueId gleichwertig.

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. 

Später, als ich gehen, um die nächste verfügbare ID abzurufen, die g_nextUniqueId die InterlockedIncrement64 wirkt auf wird die richtige sein, der einen Wert von 0, da der Anfangswert an die falsche Adresse geschrieben wurde.

Hoffentlich macht das Sinn (die Problembeschreibung, das ist).

Warum schreibt die g_nextUniqueId = 1 + lastId; Zeile an die falsche Adresse? Wenn ich den Typ zurück zu unsigned long ändere, funktioniert der Code korrekt.

Im Moment die einzige Lösung, die ich mit oben kommen kann ist das Kopieren &g_nextUniqueId auf ein void* und dann wieder auf ein volatile unsigned __int64 Gießen und zuweisen.

+0

Das mag dumm klingen, aber meine erste Ahnung ist, dass Sie eine vollständige Neukompilierung durchführen müssen. –

+0

Zuerst dachte ich, aber ich habe eine gemacht, bevor ich mit dem Testen begann und es abbrach. Ich werde es versuchen, nur für den Fall. –

+0

'unsigned __int64 g_nextUniqueId volatile;' - das ist eine ungültige Deklaration, du meintest wahrscheinlich 'volatile unsigned __int64 g_nextUniqueId' –

Antwort

2

Klingt wie Sie müssen eine vollständige Neukompilierung tun.

Dies ist häufig der Fall, wenn Sie einen Typ ändern, der in mehreren Übersetzungseinheiten verwendet wird. Manchmal wird der Abhängigkeitsprüfer verwirrt.

Verwandte Themen