首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++ 0xC0000005 訪問沖突:m_KeyboardDevice 指針未正確初始化

     編輯:程式設計綜合問答

錯誤現場

void DInputClass::GetInput() {
    HRESULT hr = m_KeyboardDevice->GetDeviceState(sizeof(m_keyBuffer), (void**)&m_keyBuffer);
    // ↑ 此處觸發 0xC0000005: 讀取位置 0x00000004 時發生訪問沖突
}

錯誤碼解讀

  • 0xC0000005 = STATUS_ACCESS_VIOLATION,典型的空指針/野指針解引用
  • 0x00000004 = 偏移量 4 字節,暗示訪問結構體/類的第 2 個成員(索引 1)
  • 結合 m_KeyboardDevice->GetDeviceState(...),說明 m_KeyboardDevice 本身為 nullptr 或已釋放懸空指針

根因排查清單

  1. DirectInput 創建失敗未檢查:DirectInput8Create、CreateDevice 返回值未驗證,導致 m_KeyboardDevice 為空
  2. 設備丟失未重置:設備被其他進程獨佔、系統休眠喚醒後,需調用 Acquire() 重新獲取,但代碼中 if(hr) 判斷邏輯反了(FAILED(hr) 才需重試)
  3. 線程安全問題:多線程並發調用 GetInput() 時,設備指針可能在別處被 Release()
  4. 對象生命週期管理:DInputClass 構造函數中未初始化 m_KeyboardDevice = nullptr,析構函數未 Release()

修正代碼模板

HRESULT DInputClass::InitKeyboard(HWND hWnd) {
    // 1. 創建 DirectInput 對象
    HRESULT hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, 
                                    IID_IDirectInput8, (void**)&m_pDI, NULL);
    if (FAILED(hr)) return hr;

    // 2. 創建鍵盤設備
    hr = m_pDI->CreateDevice(GUID_SysKeyboard, &m_KeyboardDevice, NULL);
    if (FAILED(hr)) return hr;

    // 3. 設置數據格式
    hr = m_KeyboardDevice->SetDataFormat(&c_dfDIKeyboard);
    if (FAILED(hr)) return hr;

    // 4. 設置協作級別
    hr = m_KeyboardDevice->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
    if (FAILED(hr)) return hr;

    // 5. 獲取設備
    hr = m_KeyboardDevice->Acquire();
    return hr;
}

void DInputClass::GetInput() {
    if (!m_KeyboardDevice) return;  // 防禦性檢查

    HRESULT hr = m_KeyboardDevice->GetDeviceState(sizeof(m_keyBuffer), m_keyBuffer);
    if (FAILED(hr)) {
        // 設備丟失:嘗試重新獲取
        if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED) {
            hr = m_KeyboardDevice->Acquire();
            if (SUCCEEDED(hr)) {
                m_KeyboardDevice->GetDeviceState(sizeof(m_keyBuffer), m_keyBuffer);
            }
        }
    }
    // 同理處理滑鼠...
}

調試技巧

  • 在 Visual Studio 中啟用「異常設置」→ 勾選 Win32 Exceptions - c0000005,崩潰即斷點定位
  • 給指針加上 __declspec(align(8)) 或使用 ComPtr<IDirectInputDevice8> 智能指針管理生命週期
  • 輸出 hr 十六進制值對照 dinput.h 定義的 DIERR_* 錯誤碼
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved