Странная ошибка нарушения доступа
Я получаю (для меня) странную ошибку нарушения доступа во время выполнения. У меня есть класс, GUI, который содержит необработанный указатель на экземпляр другого класса, Crosshair. Однако, когда я пытаюсь получить доступ к этому указателю, я получаю ошибку во время выполнения! Я говорю о доступе к указателю, мне даже не нужно разыменовывать его, чтобы получить ошибку.
Вот ошибка:
Unhandled exception at 0x00d4c486 in GPEngine.exe: 0xC0000005: Access violation reading location 0x00000004.
Ошибка возвращается к этой строке: int a = (int)m_pCrosshair;
Который находится в GUI::Draw()
метод, представленный ниже.
РЕДАКТИРОВАТЬ:
Я нашел проблему. Это произошло в коде, который я скрывал от вас, ребята, пытаясь скрыть как можно больше ненужного кода... Проблема была в следующем:
bool PsychoBots_Game::InitGame()
{
//more code...
return true;
//////GUI
GUIOnIntialisationInfo GUIdesc;
GUIdesc.pContentManager = m_pContentManager;
GUIdesc.pDevice = m_pLevel->GetDevice();
m_pGUI = new GUI(GUIdesc);
}
Другими словами, чистая глупость... Извините за это! Я не писал первую часть этого метода, поэтому я не знал о возвращаемых значениях, так как я никогда не использовал это при инициализации своих собственных вещей...
Старый:
Код:
Crosshair.h
#pragma once
#include "D3DUtil.h"
class ContentManager;
class RenderContext;
class Crosshair
{
public:
Crosshair(ID3D10Device* pDevice, ContentManager *pContentManager);
virtual ~Crosshair();
void Draw(ID3D10Device* pDevice, int clientWidth, int clientHeight);
private:
ID3D10InputLayout* m_pVertexLayout;
ID3D10Buffer* m_pVertexBuffer;
ID3D10Effect* m_pDefaultEffect;
ID3D10EffectTechnique* m_pDefaultTechnique;
ID3D10EffectMatrixVariable* m_pWVPVariable;
ID3D10EffectShaderResourceVariable* m_pDiffuseMapVariabele;
ID3D10ShaderResourceView * m_pTextureRV;
private:
//disabled
Crosshair(const Crosshair& b);
Crosshair& operator= (const Crosshair& b);
};
Crosshair.cpp
#include "stdafx.h"
#include "Crosshair.h"
#include "ContentManager.h"
#include "RenderContext.h"
#include "vertex.h"
Crosshair::Crosshair(ID3D10Device* pDevice, ContentManager *pContentManager)
:m_pVertexLayout(nullptr)
,m_pVertexBuffer(nullptr)
,m_pDefaultEffect(nullptr)
,m_pDefaultTechnique(nullptr)
,m_pWVPVariable(nullptr)
,m_pDiffuseMapVariabele(nullptr)
,m_pTextureRV(nullptr)
{
//////Load Texture
m_pTextureRV = pContentManager->GetTexture(pDevice, _T("GUI/Crosshair.png"));
//////Load Effect & Technique
m_pDefaultEffect = pContentManager->GetEffect(pDevice, _T("Effect/Texture2D.fx"));
//get technique
m_pDefaultTechnique = m_pDefaultEffect->GetTechniqueByIndex(0);
if(!m_pDefaultTechnique->IsValid())
{
MessageBox(0,_T("Technique not valid"),_T("ERROR"),0);
exit(-1);
}
//////Get Effect Variables
m_pDiffuseMapVariabele = m_pDefaultEffect->GetVariableBySemantic("DiffuseMap")->AsShaderResource();
if(!m_pDiffuseMapVariabele->IsValid()) {
MessageBox(0,_T("Getting EffectVariable m_pDiffuseMapVariabele Failed"),_T("ERROR"),0);
exit(-1);
}
m_pWVPVariable = m_pDefaultEffect->GetVariableBySemantic("WVP")->AsMatrix();
if(!m_pWVPVariable->IsValid()) {
MessageBox(0,_T("Getting EffectVariable m_pWVPVariable Failed"),_T("ERROR"),0);
exit(-1);
}
//////Define InputLayout
D3D10_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 }
};
UINT numElements = sizeof(layout)/sizeof(layout[0]);
// Create the input layout
D3D10_PASS_DESC PassDesc;
// Get the pass decriptor from the effect technique
m_pDefaultTechnique->GetPassByIndex( 0 )->GetDesc( &PassDesc );
HR(pDevice->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &m_pVertexLayout ));
//////Build Vertexbuffer
VertexPosTex v[4];
v[0].pos = D3DXVECTOR3(-0.5f, -0.5f, 0.0f); v[0].tex.x = 0.0f; v[0].tex.y = 1.0f;
v[1].pos = D3DXVECTOR3(-0.5f, 0.5f, 0.0f); v[1].tex.x = 0.0f; v[1].tex.y = 0.0f;
v[2].pos = D3DXVECTOR3( 0.5f, -0.5f, 0.0f); v[2].tex.x = 1.0f; v[2].tex.y = 1.0f;
v[3].pos = D3DXVECTOR3( 0.5f, 0.5f, 0.0f); v[3].tex.x = 1.0f; v[3].tex.y = 0.0f;
//fill a buffer description to copy the vertexdata into graphics memory
D3D10_BUFFER_DESC bd = {};
bd.Usage = D3D10_USAGE_DEFAULT;
bd.ByteWidth = sizeof( VertexPosTex ) * sizeof(v);
bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
bd.MiscFlags = 0;
D3D10_SUBRESOURCE_DATA initData;
initData.pSysMem = v;
//create a ID3D10Buffer in graphics memory containing the vertex info
HR(pDevice->CreateBuffer( &bd, &initData, &m_pVertexBuffer ));
}
Crosshair::~Crosshair()
{
m_pVertexLayout->Release();
m_pVertexBuffer->Release();
}
void Crosshair::Draw(ID3D10Device* pDevice, int clientWidth, int clientHeight)
{
//////Set the input layout
pDevice->IASetInputLayout( m_pVertexLayout );
//more code...
}
GUI.h
#pragma once
#include "D3DUtil.h"
#include "GUIOnInitialisationInfo.h"
#include "GUIPerFrameInfo.h"
#include "GUIPerTickInfo.h"
#include "Crosshair.h"
class GUI
{
public:
virtual ~GUI();
GUI(const GUIOnIntialisationInfo& info);
void Tick(const GUIPerTickInfo& info);
void Draw(const GUIPerFrameInfo& info);
private:
Crosshair* m_pCrosshair;
};
GUI.cpp
#include "stdafx.h"
#include "GUI.h"
GUI::GUI(const GUIOnIntialisationInfo& info)
:m_pCrosshair(new Crosshair(info.pDevice, info.pContentManager))
{
}
GUI::~GUI()
{
delete m_pCrosshair;
}
void GUI::Tick(const GUIPerTickInfo& info)
{
}
void GUI::Draw(const GUIPerFrameInfo& info)
{
int a = (int)m_pCrosshair;
m_pCrosshair->Draw(info.pDevice, info.clientWidth, info.clientHeight);
}
Ошибка возвращается к этой строке: int a = (int)m_pCrosshair;
Когда я удаляю эту строку: она сломается в m_pCrosshair->Draw(info.pDevice, info.clientWidth,info.clientHeight);
С ошибкой: Unhandled exception at 0x001fc49a in GPEngine.exe: 0xC0000005: Access violation reading location 0x00000004
Вот как экземпляр GUI создается в моем приложении:
class PsychoBots_Game : public D3DApp
{
//more code...
private:
GUI* m_pGUI;
//more code...
};
(пожалуйста, не спрашивайте меня, почему у меня есть метод InitGame(), мы должны сделать это, чтобы наши учителя были счастливы [смеется])
bool PsychoBots_Game::InitGame()
{
//////GUI
GUIOnIntialisationInfo GUIdesc;
GUIdesc.pContentManager = m_pContentManager;
GUIdesc.pDevice = m_pLevel->GetDevice();
m_pGUI = new GUI(GUIdesc);
}
И наконец, WinMain:
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
TCHAR* cmdLine, int showCmd)
{
PsychoBots_Game *pGameApp= new PsychoBots_Game(hInstance);
if(pGameApp->InitApp())pGameApp->Run();
delete pGameApp;
}
Может кто-нибудь сказать мне, что является причиной проблемы? Если по какой-либо причине вам все еще нужно больше кода, просто спросите в комментарии:)
Спасибо
3 ответа
В вашем классе есть разыменование, но вы его не видите: m_pCrosshair
является членом, поэтому любой доступ будет проходить через this
указатель, который кажется 0 в соответствии с ошибкой. Я не могу найти сайт вызова GUI::Draw
, но указатель экземпляра там равен 0 или неинициализирован.
Ваш bool PsychoBots_Game::InitGame() не возвращает значение.
Вы уверены, что метод Draw вызывается в m_pGUI?
Вы уверены, что вызывается PsychoBots_Game:: InitGame ()? Из предоставленного вами кода вызывается только pGameApp->InitApp(). m_pGUI инициализируется в InitGame.
Класс GUI класса не подчиняется правилу трех (в то время как содержит указатель RAW).
Таким образом, вы, вероятно, сделали копию объекта, а исходный объект был удален, в результате чего у вас остался объект с недопустимым указателем.
Существует простой способ проверить, является ли это проблемой: Сделайте конструктор копирования и оператор присваивания, если GUI закрытым, если вы получаете ошибку времени компиляции, тогда это ваша проблема.
В качестве примечания, ваш код содержит множество указателей RAW.
Вы должны посмотреть, что на самом деле должны быть указатели, а какие могут быть обычными объектами. В местах, где у вас должны быть указатели, посмотрите на использование умных указателей.