未处理的异常(C ++)

时间:2012-12-16 21:07:12

标签: c++ visual-studio-2010

使用DIrectX9编写小游戏时遇到了一些问题。我得到了一个未处理的异常,并且在很多尝试中我似乎无法修复它。我很欣赏这个问题的一些见解。我使用了调试器,我只是不知道如何修复异常。

输出: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;
}

1 个答案:

答案 0 :(得分:1)

我不是DirectX的专家,但我会从这里开始。首先,你的InitD3D()应该返回一个bool或者返回类型而不是void,因为它可能会失败。

对于初学者,我会检查以确保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的值。如果它为null并且值为0x00000000,则表示您正在尝试使用空指针。