У меня есть сервер, который использует глобальную переменную для хранения следующего доступного уникального идентификатора.
Первоначально это было определено как unsigned long g_nextUniqueId volatile;
Я меняю все идентификаторы на 64-битные целые числа, поэтомуэта строка была изменена на unsigned __int64 g_nextUniqueId volatile;
Есть только два фрагмента кода, которые напрямую обращаются к этой переменной.
Первый - заполнить ее при запуске сервера, это очень просто, простозапускает SQL-запрос, получает значение и сохраняет его в unsigned __int64 lastId
, а затем есть оператор для его сохранения в глобальном g_nextUniqueId = 1 + lastId;
.
Другой - это функция для получения и использования следующегодоступный идентификатор.Это однострочная функция, 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.
Позже, когда я пойду, чтобы получить следующий доступный идентификатор, g_nextUniqueId
, на который действует InterlockedIncrement64
, будетправильный, который имеет значение 0, так как начальное значение было записано по неправильному адресу.
Надеюсь, это имеет смысл (то есть описание проблемы).
Почему g_nextUniqueId = 1 + lastId;
запись строки не по адресу?Если я поменяю тип обратно на unsigned long
, код будет работать правильно.
На данный момент единственное решение, которое я могу придумать, это скопировать &g_nextUniqueId
в void*
и затем привести его обратно кvolatile unsigned __int64
и присвоение.