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_nextUniqueId
nicht 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.
Das mag dumm klingen, aber meine erste Ahnung ist, dass Sie eine vollständige Neukompilierung durchführen müssen. –
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. –
'unsigned __int64 g_nextUniqueId volatile;' - das ist eine ungültige Deklaration, du meintest wahrscheinlich 'volatile unsigned __int64 g_nextUniqueId' –