使用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;
}
答案 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
,则表示您正在尝试使用空指针。