2012-12-16 209 views
-2

我用DIrectX9編寫小遊戲時遇到了一些問題。我得到了一個未處理的異常,並且在很多嘗試中,我似乎無法修復它。我希望對此問題有所瞭解。我使用了調試器,我只是不知道如何修復這個異常。未處理的異常(C++)

輸出:AACF.exe中0x00061afd未處理的異常:0xC0000005:訪問衝突讀取位置0x00000000。

看來「數據」結構中的數據全部等於0x00000000;我該如何解決這個問題?

該異常在System.cpp中進行了註釋。

異常位置文件:

// System.cpp // 

#include "Core.h" 

struct { 
    LPDIRECT3D9 D3D; 
    LPDIRECT3DDEVICE9 D3DDEV; 
    LPD3DXSPRITE D3DSPT; 
    LPD3DXFONT DXFONT; 
    LPDIRECT3DTEXTURE9 DisplayTexture; 
} Data; 

void System::InitD3D(bool Windowed, int ScreenW, int ScreenH) { 
    Data.D3D = Direct3DCreate9(D3D_SDK_VERSION); 
    D3DPRESENT_PARAMETERS D3DPP; 

    ZeroMemory(&D3DPP, sizeof(D3DPP)); 
    D3DPP.Windowed = Windowed; 
    D3DPP.SwapEffect = D3DSWAPEFFECT_DISCARD; 
    D3DPP.hDeviceWindow = hWnd; 
    D3DPP.BackBufferFormat = D3DFMT_X8R8G8B8; 
    D3DPP.BackBufferWidth = ScreenW; 
    D3DPP.BackBufferHeight = ScreenH; 
    D3DPP.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; 

    Data.D3D->CreateDevice(D3DADAPTER_DEFAULT, 
         D3DDEVTYPE_HAL, 
         hWnd, 
         D3DCREATE_SOFTWARE_VERTEXPROCESSING, 
         &D3DPP, 
         &Data.D3DDEV); 
    D3DXCreateSprite(Data.D3DDEV, &Data.D3DSPT); 

    Load_Display(); 

    return; 
} 

void System::Render_Frame(void) { 
    // EXCEPTIONS START HERE 
    // Data.D3DDEV->Clear gives an exception 
    Data.D3DDEV->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0F, 0); // Exception line 
    Data.D3DDEV->BeginScene(); 
    Data.D3DSPT->Begin(D3DXSPRITE_ALPHABLEND); 

    Draw_Display(); 

    Data.D3DSPT->End(); 
    Data.D3DDEV->EndScene(); 
    Data.D3DDEV->Present(NULL, NULL, NULL, NULL); 
    return; 
} 

void System::CleanD3D() { 
    Data.DisplayTexture->Release(); 
    Data.D3DDEV->Release(); 
    Data.D3D->Release(); 
    return; 
} 

void System::Load_Display() { 
    LoadTexture(&Data.DisplayTexture, L"DisplaySprites.png"); 
    D3DXCreateFont(Data.D3DDEV, 20, 0, FW_BOLD, 1, false, DEFAULT_CHARSET, 
        OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
        L"Arial", &Data.DXFONT); 
    return; 
} 

void System::Draw_Display() { 
    return; 
} 

void System::LoadTexture(LPDIRECT3DTEXTURE9* Texture, LPCTSTR FileName) { 
    D3DXCreateTextureFromFileEx(Data.D3DDEV, FileName, D3DX_DEFAULT, D3DX_DEFAULT, 
           D3DX_DEFAULT, NULL, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_DEFAULT, 
           D3DX_DEFAULT, D3DCOLOR_XRGB(255, 0, 255), NULL, NULL, Texture); 
    return; 
} 

void System::DrawTexture(LPDIRECT3DTEXTURE9 Texture, RECT TexCoords, float X, float Y, int A) { 
    D3DXVECTOR3 Center(0.0F, 0.0F, 0.0F), Position(X, Y, 0.0F); 
    Data.D3DSPT->Draw(Texture, &TexCoords, &Center, &Position, D3DCOLOR_ARGB(A,255,255,255)); 
    return; 
} 

void System::DrawString(const char* Text, int Count, RECT Rect, float X, float Y, int A, int R, int G, int B) { 
    SetRect(&Rect, 0, 0, (int)X, (int)Y); 
    Data.DXFONT->DrawTextA(NULL, 
         Text, 
         Count, 
         &Rect, 
         DT_BOTTOM | DT_RIGHT, 
         D3DCOLOR_ARGB(A, R, G, B)); 
} 

void System::DrawNumber(int SetValue, RECT Rect, float X, float Y, int A, int R, int G, int B) { 
    SetRect(&Rect, 0, 0, (int)X, (int)Y); 
    static char Number[10]; 
    _itoa_s(SetValue, Number, 10); 
    Data.DXFONT->DrawTextA(NULL, 
         (LPCSTR)&Number, 
         strlen((LPCSTR)&Number), 
         &Rect, 
         DT_BOTTOM | DT_RIGHT, 
         D3DCOLOR_ARGB(A, R, G, B)); 
} 

System.cpp標題:

// System.h // 

// Include Guard // 
#ifndef _SYSTEM_H 
#define _SYSTEM_H 

#include "Core.h" 

// Globalizing Data Structure 
struct Data; 

// Define screen resolution and keyboard macros 
#define SCREEN_WIDTH (1000) 
#define SCREEN_HEIGHT (700) 
#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) 
#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1) 

// WinProc ProtoType 
LRESULT CALLBACK WindowProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam); 

class System { 
private: 
    HWND hWnd; 
public: 
    System() {}; 
    void InitD3D(bool Windowed, int ScreenW, int ScreenH); 
    void Render_Frame(void); 
    void CleanD3D(void); 
    void Load_Display(); 
    void Draw_Display(); 
    void LoadTexture(LPDIRECT3DTEXTURE9* Texture, LPCTSTR FileName); 
    void DrawTexture(LPDIRECT3DTEXTURE9 Texture, RECT TexCoords, float X, float Y, int A); 
    void DrawString(const char* Text, int Count, RECT Rect, float X, float Y, int A, int R, int G, int B); 
    void DrawNumber(int SetValue, RECT Rect, float X, float Y, int A, int R, int G, int B); 
}; 

#endif 

其他文件:

// Core.h // 

// Include Guard // 
#ifndef _CORE_H 
#define _CORE_H 

// Pragma Comments 
#pragma comment(lib, "d3d9.lib") 
#pragma comment(lib, "d3dx9.lib") 

// External Include <> // 
#include <Windows.h> 
#include <WindowsX.h> 
#include <d3d9.h> 
#include <d3dx9.h> 

#include <vector> 
#include <map> 
#include <iostream> 
#include <tchar.h> 

// Internal Incldue "" // 
#include "System.h" 

#endif 

// Core.cpp // 

#include "Core.h" 


int WINAPI WinMain(HINSTANCE hInstance, 
        HINSTANCE hPrevInstance, 
        LPSTR lpCmdLine, 
        int nCmdShow) { 
    System Sys; 
    HWND hWnd; 
    WNDCLASSEX WC; 

    ZeroMemory(&WC, sizeof(WNDCLASSEX)); 

    WC.cbSize = sizeof(WNDCLASSEX); 
    WC.style = CS_HREDRAW | CS_VREDRAW; 
    WC.lpfnWndProc = (WNDPROC)WindowProc; 
    WC.hInstance = hInstance; 
    WC.hCursor = LoadCursor(NULL, IDC_ARROW); 
    WC.lpszClassName = L"WindowClass"; 

    RegisterClassEx(&WC); 
    hWnd = CreateWindowEx(NULL, L"WindowClass", L"Game Name", 
          WS_OVERLAPPEDWINDOW, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 
          NULL, NULL, hInstance, NULL); 
    ShowWindow(hWnd, nCmdShow); 
    // Set up Direct3D 
    Sys.InitD3D(TRUE, SCREEN_WIDTH, SCREEN_HEIGHT); 
    // Enter Main Loop 
    MSG Msg; 
    while(TRUE) { 
     DWORD Starting_Point = GetTickCount(); 
     if(PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) { 
      if(Msg.message == WM_QUIT) 
       break; 
      TranslateMessage(&Msg); 
      DispatchMessage(&Msg); 
     } 
     Sys.Render_Frame(); 
     // Check escape key 
     if(KEY_DOWN(VK_ESCAPE)) 
      PostMessage(hWnd, WM_DESTROY, 0, 0); 
     while((GetTickCount() - Starting_Point) < 25); 
    } 
    Sys.CleanD3D(); 
    return Msg.wParam; 
} 

LRESULT CALLBACK WindowProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) { 
    switch(Message) { 
    case WM_DESTROY: 
     { 
      PostQuitMessage(0); 
      return 0; 
     } break; 
    } 
    return DefWindowProc(hWnd, Message, wParam, lParam); 
} 

bool CheckCollision(float Ax, float Ay, float Aw, float Ah, float Bx, float By, float Bw, float Bh) { 
    if(Ay+Ah < By) return false; 
    else if(Ay > By+Bh) return false; 
    else if(Ax+Aw < Bx) return false; 
    else if(Ax > Bx+Bw) return false; 

    return true; 
} 
+3

您是否嘗試使用調試器並查看引發異常的確切位置? –

+0

你已經粘貼了太多的代碼,以便我們能夠合理地嘗試猜測問題出在哪裏。一些建議:1)使用調試器來查找@Esteban建議的錯誤。 2)否則,使用trace語句來確定程序何時退出,並因此將故障本地化爲特定代碼段。 3)將程序縮減爲[sscce](http://sscce.org/) - 這樣做時可能會發現問題,即使您不這樣做,它也會使我們更容易幫助您。 – Mac

+0

我對異常開始的位置發表評論;我認爲閱讀時很明顯。 –

回答

1

我不是在DirectX方面的專家,但在這裏就是我將開始。首先,你的InitD3D()可能應該返回一個bool或者具有非空的返回類型,因爲它可能會失敗。

對於初學者,我會檢查以確保Create()函數成功。例如,我可能會添加類似:

//Returns NULL pointer on failure. 
Data.D3D = Direct3DCreate9(D3D_SDK_VERSION); 

if(!Data.D3D) 
    return false; 

而當你去創建設備:

HRESULT hr = Data.D3D->CreateDevice(D3DADAPTER_DEFAULT, 
        D3DDEVTYPE_HAL, 
        hWnd, 
        D3DCREATE_SOFTWARE_VERTEXPROCESSING, 
        &D3DPP, 
        &Data.D3DDEV); 

if(hr != D3D_OK) 
    return false; 

我至少會做一些基本的錯誤檢查。如果設備已成功創建並且在通話時有值,則可以排除該情況。自從我使用DirectX以來,已經有一段時間了,所以在返回false之前,您可能必須先釋放()/清理一些內容,但這是基本的想法。

很容易檢查通話時設備是否爲值。在發生異常的行上設置斷點。當你點擊它時,在調試器中檢查Data.D3DDEV的值。如果它爲空,並且值爲0x00000000,則您試圖引用空指針。