DirectX9 中的访问冲突

发布于 2024-12-03 02:19:55 字数 5551 浏览 3 评论 0原文

最简单的方法是:每当我运行代码时,它都会抛出访问冲突错误。我得出的结论是,这是在函数 System::renderFrame() 内调用 this->d3ddev.(whatever) 的错误。这个函数从第 112 行开始。如果有人能在这里帮助我,那就太好了。 (顺便说一句,我已经完成了这个工作,但我想将此代码放入类中,这就是我开始遇到麻烦的地方。另外,之前有人告诉我要确保初始化所有指针。它们是通过以下方式初始化的: d3d->createDevice())

system.h

#ifndef SYSTEM_H
#define SYSTEM_H

#include "stdinc.h"


class System {
  private:
    void initD3D (void);
    void cleanD3D (void);
    void setUpHWND (HINSTANCE, LPSTR, int);
    static LRESULT CALLBACK StaticWindowProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT WindowProc(HWND, UINT, WPARAM, LPARAM);

    HWND window;
    WNDCLASSEX windowClass;
    LPDIRECT3D9 d3d;
    LPDIRECT3DDEVICE9 d3ddev;
    D3DPRESENT_PARAMETERS d3dpp;

    HINSTANCE hInstance;
    LPSTR lpCmdLine;
    int nCmdShow;
  public:
    System (void);
    System (HINSTANCE, LPSTR, int);
    System (const System&);
    ~System (void);

    void renderFrame (void);
};

#endif

system.cpp

#include "system.h"

//////////////////////////////////////////////////
// Class: System
// Private
//////////////////////////////////////////////////

void System::initD3D (void) {
    this->d3d = Direct3DCreate9(D3D_SDK_VERSION);

    ZeroMemory(&(this->d3dpp), sizeof(d3dpp));
    this->d3dpp.Windowed = WINDOWED;
    this->d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    this->d3dpp.hDeviceWindow = this->window;
    this->d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
    this->d3dpp.BackBufferWidth = SCREEN_WIDTH;
    this->d3dpp.BackBufferHeight = SCREEN_HEIGHT;
    this->d3dpp.EnableAutoDepthStencil = TRUE;
    this->d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

    this->d3d->CreateDevice(D3DADAPTER_DEFAULT,
        D3DDEVTYPE_HAL,
        this->window,
        D3DCREATE_SOFTWARE_VERTEXPROCESSING,
        &(this->d3dpp),
        &(this->d3ddev));

    this->d3ddev->SetRenderState(D3DRS_LIGHTING, FALSE);
    this->d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
    this->d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE);
};

void System::cleanD3D (void) { 
    this->d3d->Release();
    this->d3ddev->Release();
};

void System::setUpHWND (
                        HINSTANCE hInstance,
                        LPSTR lpCmdLine,
                        int nCmdShow) {
    this->hInstance = hInstance;
    this->lpCmdLine = lpCmdLine;
    this->nCmdShow = nCmdShow;

    ZeroMemory(&(this->windowClass), sizeof(WNDCLASSEX));
    this->windowClass.cbSize = sizeof(WNDCLASSEX);
    this->windowClass.style = CS_HREDRAW | CS_VREDRAW;
    this->windowClass.lpfnWndProc = System::StaticWindowProc;
    this->windowClass.hInstance = this->hInstance;
    this->windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    this->windowClass.lpszClassName = "WindowClass";
    RegisterClassEx(&(this->windowClass));

    this->window = CreateWindowEx(NULL, "WindowClass", "The Direct3D Program", 
        WS_OVERLAPPEDWINDOW, SCREEN_X, SCREEN_Y, SCREEN_WIDTH, SCREEN_HEIGHT,
        NULL, NULL, this->hInstance, NULL);
};

LRESULT CALLBACK System::StaticWindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    System *SystemPtr = (System*)GetWindowLong(hWnd, GWLP_USERDATA);

    if(SystemPtr)
    {
        return SystemPtr->WindowProc(hWnd, message, wParam, lParam);
    }
    else
    {
       return DefWindowProc(hWnd, message, wParam, lParam);
    }
};

LRESULT System::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);
};

//////////////////////////////////////////////////
// Class: System
// Public
//////////////////////////////////////////////////

System::System (void) {
};

System::System (
                HINSTANCE hInstance,
                LPSTR lpCmdLine,
                int nCmdShow) {
    this->setUpHWND(hInstance, lpCmdLine, nCmdShow);

    ShowWindow(this->window, this->nCmdShow);

    this->initD3D();
};

System::System (const System &) {
};

System::~System (void) {
    this->cleanD3D();
};

void System::renderFrame (void) {
    // Update the camera here

    // Update objects

    // Clear objects

    // FOR SOME REASON THERE IS AN ERROR HERE
    this->d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 0);
    this->d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

    this->d3ddev->BeginScene();

    // Draw objects

    // Finish up
    this->d3ddev->EndScene(); 

    this->d3ddev->Present(NULL, NULL, NULL, NULL); 
};

main.cpp

#include "system.h"

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow) {
    System MainSys;
    MainSys = System(hInstance, lpCmdLine, nCmdShow);

    // Enter the main loop
    MSG msg;

    while (TRUE)
    {
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        if (msg.message == WM_QUIT)
            break;

        MainSys.renderFrame();
    }

    // Clean up DirectX and the COM
    //delete MainSys;

    return msg.wParam;
};

Easiest way to put this: My code is throwing an access violation error whenever I run it. I have concluded it is the fault of calling this->d3ddev.(whatever) inside of the function System::renderFrame(). This function starts on line 112. If anyone could help me out here, that'd be great.
(by the way, I've gotten this working, but I wanted to put this code into classes, and that's where I started having my troubles. Also, I was told before to make sure to initialize all pointers. They are initialized, through d3d->createDevice())

system.h

#ifndef SYSTEM_H
#define SYSTEM_H

#include "stdinc.h"


class System {
  private:
    void initD3D (void);
    void cleanD3D (void);
    void setUpHWND (HINSTANCE, LPSTR, int);
    static LRESULT CALLBACK StaticWindowProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT WindowProc(HWND, UINT, WPARAM, LPARAM);

    HWND window;
    WNDCLASSEX windowClass;
    LPDIRECT3D9 d3d;
    LPDIRECT3DDEVICE9 d3ddev;
    D3DPRESENT_PARAMETERS d3dpp;

    HINSTANCE hInstance;
    LPSTR lpCmdLine;
    int nCmdShow;
  public:
    System (void);
    System (HINSTANCE, LPSTR, int);
    System (const System&);
    ~System (void);

    void renderFrame (void);
};

#endif

system.cpp

#include "system.h"

//////////////////////////////////////////////////
// Class: System
// Private
//////////////////////////////////////////////////

void System::initD3D (void) {
    this->d3d = Direct3DCreate9(D3D_SDK_VERSION);

    ZeroMemory(&(this->d3dpp), sizeof(d3dpp));
    this->d3dpp.Windowed = WINDOWED;
    this->d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    this->d3dpp.hDeviceWindow = this->window;
    this->d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
    this->d3dpp.BackBufferWidth = SCREEN_WIDTH;
    this->d3dpp.BackBufferHeight = SCREEN_HEIGHT;
    this->d3dpp.EnableAutoDepthStencil = TRUE;
    this->d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

    this->d3d->CreateDevice(D3DADAPTER_DEFAULT,
        D3DDEVTYPE_HAL,
        this->window,
        D3DCREATE_SOFTWARE_VERTEXPROCESSING,
        &(this->d3dpp),
        &(this->d3ddev));

    this->d3ddev->SetRenderState(D3DRS_LIGHTING, FALSE);
    this->d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
    this->d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE);
};

void System::cleanD3D (void) { 
    this->d3d->Release();
    this->d3ddev->Release();
};

void System::setUpHWND (
                        HINSTANCE hInstance,
                        LPSTR lpCmdLine,
                        int nCmdShow) {
    this->hInstance = hInstance;
    this->lpCmdLine = lpCmdLine;
    this->nCmdShow = nCmdShow;

    ZeroMemory(&(this->windowClass), sizeof(WNDCLASSEX));
    this->windowClass.cbSize = sizeof(WNDCLASSEX);
    this->windowClass.style = CS_HREDRAW | CS_VREDRAW;
    this->windowClass.lpfnWndProc = System::StaticWindowProc;
    this->windowClass.hInstance = this->hInstance;
    this->windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    this->windowClass.lpszClassName = "WindowClass";
    RegisterClassEx(&(this->windowClass));

    this->window = CreateWindowEx(NULL, "WindowClass", "The Direct3D Program", 
        WS_OVERLAPPEDWINDOW, SCREEN_X, SCREEN_Y, SCREEN_WIDTH, SCREEN_HEIGHT,
        NULL, NULL, this->hInstance, NULL);
};

LRESULT CALLBACK System::StaticWindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    System *SystemPtr = (System*)GetWindowLong(hWnd, GWLP_USERDATA);

    if(SystemPtr)
    {
        return SystemPtr->WindowProc(hWnd, message, wParam, lParam);
    }
    else
    {
       return DefWindowProc(hWnd, message, wParam, lParam);
    }
};

LRESULT System::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);
};

//////////////////////////////////////////////////
// Class: System
// Public
//////////////////////////////////////////////////

System::System (void) {
};

System::System (
                HINSTANCE hInstance,
                LPSTR lpCmdLine,
                int nCmdShow) {
    this->setUpHWND(hInstance, lpCmdLine, nCmdShow);

    ShowWindow(this->window, this->nCmdShow);

    this->initD3D();
};

System::System (const System &) {
};

System::~System (void) {
    this->cleanD3D();
};

void System::renderFrame (void) {
    // Update the camera here

    // Update objects

    // Clear objects

    // FOR SOME REASON THERE IS AN ERROR HERE
    this->d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 0);
    this->d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

    this->d3ddev->BeginScene();

    // Draw objects

    // Finish up
    this->d3ddev->EndScene(); 

    this->d3ddev->Present(NULL, NULL, NULL, NULL); 
};

main.cpp

#include "system.h"

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow) {
    System MainSys;
    MainSys = System(hInstance, lpCmdLine, nCmdShow);

    // Enter the main loop
    MSG msg;

    while (TRUE)
    {
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        if (msg.message == WM_QUIT)
            break;

        MainSys.renderFrame();
    }

    // Clean up DirectX and the COM
    //delete MainSys;

    return msg.wParam;
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

何处潇湘 2024-12-10 02:19:55

我尝试编译您的代码并将以下几行更改为:

System MainSys;
MainSys = System(hInstance, lpCmdLine, nCmdShow);

并且

System MainSys(hInstance, lpCmdLine, nCmdShow);

它有效。

我承认我不知道它失败的确切原因,但是您的 System 类中有很多东西,并且您正在构造它的两个实例(在两行中一次),然后将一个实例分配给另一个实例。无论如何,这都不是一个好主意,而且没有必要。我猜它与 Direct3D 引用计数有关,并且当类被复制到第二行中的 MainSys 时,您并没有遵守它。

编辑

我刚刚注意到MainSys的析构函数在使用System(hInstance, lpCmdLine, nCmdShow); 构造​​类后被调用;所以刚刚获得的设备再次被Released() 。

I tried to compile your code and changed the following lines:

System MainSys;
MainSys = System(hInstance, lpCmdLine, nCmdShow);

into

System MainSys(hInstance, lpCmdLine, nCmdShow);

and it worked.

I admit I don't know exactly why it fails, but there's a lot of stuff in your System class and you are constructing two instances of it (once in both lines) and then assign one to the other. This is not a good idea in any case and unnecessary. I guess it has somethinig to do with Direct3D reference counting and you are not honoring it when the class gets copied to MainSys in the second line.

EDIT

I just noticed that the destructor of MainSys gets called after the class is constructed with System(hInstance, lpCmdLine, nCmdShow); So the just obtained device is Released() again.

指尖微凉心微凉 2024-12-10 02:19:55

我在这里没有立即看到任何错误,但很容易错过一些东西。
我建议检查每个 d3d api 调用的 HRESULTS,以确保某些内容没有失败,并全部使用assert(pointer != NULL) 来尝试捕获问题。或者使用调试器逐步执行并查看变量以确定何时开始失败。

另外,如果您还没有这样做,请打开 d3d9 调试版本并查看日志。它经常告诉你你错过了什么。

I don't see anything imeediately wrong here but its easy to miss something.
I suggest checking the HRESULTS from every d3d api call to make sure something didn't fail, and assing assert(pointer != NULL) all over to try to catch the problem. Or step through with a debugger and look at the variables to determine when it starts to fail.

Also, if you've not done so, turn on the d3d9 debug version and look at the log. It often tells you what you've missed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文