【问题标题】:Exception thrown at 0x0131EB06 Visual Studio在 0x0131EB06 Visual Studio 引发异常
【发布时间】:2015-06-09 17:10:55
【问题描述】:

我是 Directx 的新手,我想测试一个在窗口中绘制圆圈的简单 direct2d 应用程序。我正在使用 Visual Studio 专业版。当我使用本地 Windows 调试器运行名为 D2D 测试引擎的程序时,我会收到以下错误:

Exception thrown at 0x0140EB06 in D2D Test Engine.exe: 0xC0000005: Access violation reading location 0x00000008.
Exception thrown at 0x0140EB06 in D2D Test Engine.exe: 0xC0000005: Access violation reading location 0x00000008.
Exception thrown at 0x0140EB06 in D2D Test Engine.exe: 0xC0000005: Access violation reading location 0x00000008.

我无法弄清楚我的程序出了什么问题。 这是我的代码:

#include <Windows.h>
#include "Graphics.h"
Graphics* graphics;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (uMsg == WM_DESTROY) {
    PostQuitMessage(0);
    return 0;
}
graphics->BeginDraw();
graphics->ClearScreen(0.0f, 0.0f, 0.5f);
graphics->DrawShape(100, 100, 50, 1.0f, 0.0, 0.0, 1.0);
graphics->EndDraw();
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPWSTR cmd, int nCmdShow) {
WNDCLASSEX windowclass;
ZeroMemory(&windowclass, sizeof(WNDCLASSEX));
windowclass.cbSize = sizeof(WNDCLASSEX);
windowclass.hbrBackground = (HBRUSH) COLOR_WINDOW;
windowclass.hInstance = hInstance;
windowclass.lpfnWndProc = WindowProc;
windowclass.lpszClassName = "MainWindow";
windowclass.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&windowclass);
RECT rect = { 0, 0, 800, 600 };
AdjustWindowRectEx(&rect, WS_EX_OVERLAPPEDWINDOW, false, WS_EX_OVERLAPPEDWINDOW);
HWND windowHandle = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, "MainWindow", "D2D Test Engine", WS_OVERLAPPEDWINDOW, 0, 0, rect.right - rect.left,      rect.bottom - rect.top, NULL, NULL, hInstance, 0);
    if (!windowHandle) {
        return -1;
    }
    graphics = new Graphics();
    if (graphics->Init(windowHandle) == false) {
        delete graphics;
        return -1;
    }
    ShowWindow(windowHandle, nCmdShow);
    MSG message;
    while (GetMessage(&message, NULL, 0, 0)) {
        DispatchMessage(&message);
    }
    return 0;
}

下一个文件:

#pragma once
#include <Windows.h>
#include <d2d1.h>
class Graphics
{
ID2D1Factory* factory;
ID2D1HwndRenderTarget* renderTarget;
public:
Graphics();
virtual ~Graphics();
bool Init(HWND windowHandle);
void BeginDraw() {renderTarget->BeginDraw();}
void EndDraw() {renderTarget->EndDraw();}
void ClearScreen(float r, float g, float b);
void DrawShape(float x, float y, float radius, float r, float g, float b, float a);
};

下一个文件:

#include "Graphics.h"
#include <d2d1.h>
#include <Windows.h>
Graphics::Graphics()
{
factory = NULL;
renderTarget = NULL;
}
Graphics::~Graphics()
{
if (factory) {
    factory->Release();
}
if (renderTarget) {
    renderTarget->Release();
}
}
bool Graphics::Init(HWND windowHandle) {
HRESULT res = D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, &factory);
if (res != S_OK) {
    return false;
}
RECT rect;
GetClientRect(windowHandle, &rect);
res = factory->CreateHwndRenderTarget(D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties(windowHandle, D2D1::SizeU(rect.right, rect.bottom)), &renderTarget);
if (res != S_OK) {
    return false;
}
return true;
}
void Graphics::ClearScreen(float r, float g, float b) {
renderTarget->Clear(D2D1::ColorF(r, g, b));
}
void Graphics::DrawShape(float x, float y, float radius, float r, float g, float b, float a) {
ID2D1SolidColorBrush* brush;

renderTarget->CreateSolidColorBrush(D2D1::ColorF(r, g, b, a), &brush);
renderTarget->DrawEllipse(D2D1::Ellipse(D2D1::Point2F(x, y), radius, radius), brush, 3.0f);
brush->Release();
}

当我不调用 BeginDraw()、ClearScreen、DrawShape 和 EndDraw 时,会出现一个窗口并且它运行良好,所以我认为这与它们有关。

【问题讨论】:

  • 我猜你在某处有一个NULL 指针访问。您应该在调试器中运行并让调试器在崩溃的位置停止。
  • 使用调试器。几乎可以肯定是一个 NULL 指针,您可以通过它访问结构成员。
  • 请格式化/缩进您的代码以获得更好的可读性。
  • 调试器停止在 void BeginDraw(){renderTarget->BeginDraw();}

标签: c++ visual-studio direct2d


【解决方案1】:

我想出了答案。我对这个 directx 东西很陌生,我正在使用教程来构建它。我需要做的是将我调用的所有函数放入 if 语句中。这就是我所做的:

if (uMsg == WM_PAINT) {
    graphics->BeginDraw();
    graphics->ClearScreen(0.0f, 0.0f, 0.5f);
    graphics->DrawShape(100, 100, 50, 1.0f, 0.0, 0.0, 1.0);
    graphics->EndDraw();
}

抱歉,我是新手。

【讨论】:

    【解决方案2】:

    看来,WM_CREATE 消息有问题。 此消息在调用 CreateWindowEx 时发送。

    Graphics* graphics = NULL; // it's better to zero pointer in C++.
    

    简单的解决方案 - 将图形设置为 null 并在 WindowProc 函数中进行检查。

    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        if (uMsg == WM_DESTROY) {
          PostQuitMessage(0);
          return 0;
       } 
    
       if (graphics) {
         graphics->BeginDraw();
         graphics->ClearScreen(0.0f, 0.0f, 0.5f);
         graphics->DrawShape(100, 100, 50, 1.0f, 0.0, 0.0, 1.0);
         graphics->EndDraw();
       }
       return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    

    【讨论】:

    • 好的,所以当我创建对象方法时,我将它设置为 NULL?另外,检查是什么意思?我应该在WindowProc函数中做什么?
    • 我已经更新了我的帖子。你也可以阅读这个article 关于OpenGL 和window proc 的内容。您可以处理 WM_ACTIVATE 消息并设置 bool 标志,您可以渲染。而且,作为改进,您应该避免使用 go 全局变量并传递您的指针 link
    • 对不起,可以直接回复你的消息,但是WM_PAINT对于游戏来说不是很好的解决方案,它可能会降低fps。
    • 对替换 WM_PAINT 有什么建议吗?
    • 最好的方法——模式渲染到其他线程,在窗口和上下文初始化之后循环绘制场景,只计算帧时间并可能限制它。如果渲染应该处于活动状态(窗口激活和停用),则从主线程设置标志。你应该阅读这篇关于游戏编程模式的book
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-28
    • 2018-02-21
    • 2016-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多