Я очень смущен, и я думаю, что мой отладчик лжет мне. В моем коде есть следующий цикл:
MyClass::UploadFile(CString strFile)
{
...
static DWORD dwLockWaitTime = EngKey::GetDWORD(DNENG_SERVER_UPLOAD_LOCK_WAIT_TIME, DNENG_SERVER_UPLOAD_LOCK_WAIT_TIME_DEFAULT);
static DWORD dwLockPollInterval = EngKey::GetDWORD(DNENG_SERVER_UPLOAD_LOCK_POLL_INTERVAL, DNENG_SERVER_UPLOAD_LOCK_POLL_INTERVAL_DEFAULT);
LONGLONG llReturnedOffset(0LL);
BOOL bLocked(FALSE);
for (DWORD sanity = 0; (sanity == 0 || status == RESUMABLE_FILE_LOCKED) && sanity < (dwLockWaitTime / dwLockPollInterval); sanity++)
{
...
Этот цикл был выполнен сотни раз в течение моей программы, и две статические переменные нигде не изменялись в коде, они записываются только один раз, когда они статически инициализируются и считываются из условий цикла и в другом месте. Поскольку они являются пользовательскими настройками, которые считываются из реестра Windows, они почти всегда имеют постоянные значения dwLockWaitTime = 60 и dwLockPollInterval = 5. Таким образом, цикл всегда выполняет 60/5.
Очень редко я получаю аварийный дамп, который показывает, что эта строка кода породила деление на нулевую ошибку. Я проверил, что говорит WinDbg, и он показывает:
FAULTING_IP:
procname!CServerAgent::ResumableUpload+54a [serveragent.cpp @ 725]
00000001`3f72d74a f73570151c00 div eax,dword ptr [proc!dwLockPollInterval (00000001`3f8eecc0)]
EXCEPTION_RECORD: ffffffffffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 000000013f72d74a (proc!CServerAgent::ResumableUpload+0x000000000000054a)
ExceptionCode: c0000094 (Integer divide-by-zero)
ExceptionFlags: 00000000
NumberParameters: 0
ERROR_CODE: (NTSTATUS) 0xc0000094 - {EXCEPTION} Integer division by zero.
Я проверил код ассемблера, и он показывает, что авария произошла в этой команде div.
00000001`3f72d744 8b0572151c00 mov eax,dword ptr [dwLockWaitTime (00000001`3f8eecbc)]
00000001`3f72d74a f73570151c00 div eax,dword ptr [dwLockPollInterval (00000001`3f8eecc0)]
Итак, как вы можете видеть, значение в 000000013f8eecbc
было перемещено в eax
, а затем eax
было разделено на значение 000000013f8eecc0
.
Что это за два значения, которые вы задаете?
0:048> dd 00000001`3f8eecbc
00000001`3f8eecbc 0000003c 00000005 00000001 00000000
00000001`3f8eeccc 00000000 00000002 00000000 00000000
00000001`3f8eecdc 00000000 7fffffff a9ad25cf 7fffffff
00000001`3f8eecec a9ad25cf 00000000 00000000 00000000
00000001`3f8eecfc 00000000 00000000 00000000 00000000
00000001`3f8eed0c 00000000 00000000 00000000 00000000
00000001`3f8eed1c 00000000 00000000 00000000 00000000
00000001`3f8eed2c 00000000 00000000 00000000 00000000
0:048> dd 000000013f8eecc0
00000001`3f8eecc0 00000005 00000001 00000000 00000000
00000001`3f8eecd0 00000002 00000000 00000000 00000000
00000001`3f8eece0 7fffffff a9ad25cf 7fffffff a9ad25cf
00000001`3f8eecf0 00000000 00000000 00000000 00000000
00000001`3f8eed00 00000000 00000000 00000000 00000000
00000001`3f8eed10 00000000 00000000 00000000 00000000
00000001`3f8eed20 00000000 00000000 00000000 00000000
00000001`3f8eed30 00000000 00000000 00000000 00000000
Константы 60
и 5
точно так, как я ожидал. Итак, где деление на ноль??? Является ли мой отладчик лживым? Разумеется, деление на ноль было сброшено аппаратными средствами, поэтому он не мог ошибиться в этом? И если это было деление на ноль в другом месте моего кода, каковы шансы, что отладчик покажет указатель инструкции именно в этом месте? Признаюсь, я в тупике.