I'm writing a test application on DirectX11, and I have 2 classes "Box" and "camera" . "Box" is a cube which is to be drawn on the screen, and this is "camera":
class camera
{
public :
const camera operator=(const camera& fv) const
{
return fv;
}
XMVECTOR eye;
XMVECTOR at;
XMVECTOR up;
XMVECTOR right;
XMVECTOR left;
XMVECTOR down;
float pitch; //x
float roll; //z
float yaw; //y
XMMATRIX View;
XMMATRIX Projection;
camera();
camera(XMVECTOR eye, XMVECTOR at, XMVECTOR up, float movingOffset, float radius);
void Move(XMVECTOR Offset);
void MoveCameraRight(float offset);
void Rotate(XMVECTOR offset);
void MoveCameraLeft(float offset);
void MoveCameraUp(float offset);
void MoveCameraDown(float offset);
void MoveCameraCloser(float offset);
} ;
I'm working in Visual Studio 2012, and all was perfect, until I decided to build my solution under Release config. Camera constructor has always fallen on "Unhandled exception: Acces violation reading location..." on different addresses near 0x0. I know why it's happening, I've checked all of the pointers I've used, and I completely don't understand, what is happening. Here is the beginning of the file with the WinMain function:
#include <stdio.h>
#include "DIMouse.h"
#include <string>
#include <sstream>
#include <iostream>
HINSTANCE g_hInst = nullptr;
HWND g_hWnd = nullptr;
HRESULT hr = S_OK;
D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;
D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
ID3D11Device* g_pd3dDevice = nullptr;
ID3D11DeviceContext* g_pImmediateContext = nullptr;
IDXGISwapChain* g_pSwapChain = nullptr;
ID3D11RenderTargetView* g_pRenderTargetView = nullptr;
ID3D11VertexShader* g_pVertexShader = nullptr;
ID3D11PixelShader* g_pPixelShader = nullptr;
ID3D11InputLayout* g_pVertexLayout = nullptr;
ID3D11Buffer* g_pVertexBuffer = nullptr;
ID3D11Buffer* g_pConstantBuffer = nullptr;
ID3D11Buffer* g_pIndexBuffer = nullptr;
XMMATRIX g_World; // World matrix
XMMATRIX g_View; // View matrix
XMMATRIX g_Projection; // Projection matrix
int BOXES_COUNT = 50;
int Radius = 20;
FILE* fpsLog = NULL;
Box** boxes;
camera* cam;
FPS fps;
int calculationId = 0;
HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow );
HRESULT InitDevice();
HRESULT InitGeometry();
void parseArgs(LPWSTR lpl);
void CleanupDevice();
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
void Render();
HRESULT InitCamera();
void InitCubes(int boxesCount);
cDIObject DIObject;
cMouse Mouse;
int WINAPI wWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow )
{
//parse args
parseArgs( lpCmdLine );
UNREFERENCED_PARAMETER( hPrevInstance );
UNREFERENCED_PARAMETER( lpCmdLine );
....
if (FAILED ( InitCamera()))
{
.....
InitCamera() - a function, where I call the constructor, when all crashes:
HRESULT InitCamera()
{
RECT rc;
GetClientRect( g_hWnd, &rc );
UINT width = rc.right - rc.left;
UINT height = rc.bottom - rc.top;
g_World = XMMatrixIdentity();
XMVECTOR Eye = XMVectorSet( 0.0f, 0.0f, -45, 0.0f );
XMVECTOR At = XMVectorSet( 0.0f, 0.0f, 0.0f, 0.0f );
XMVECTOR Up = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f );
g_View = XMMatrixLookAtLH( Eye, At, Up );
g_Projection = XMMatrixPerspectiveFovLH( XM_PIDIV4, width / (FLOAT)height, 0.01f, 100.0f );
cam = (camera*)malloc(sizeof(camera));
camera * c = new camera( Eye, At, Up, 0.5, Radius );
cam = c;
cam is a global pointer to camera class, don't look at me that way, this worked under VS for some time.
If I need to parse command line arguments, which are taken from lpCmdLine, I need to alloc memory, and I've thought, that the reason were memory allocations in the beginning of ..Main. I used malloc() and arrays ( with new and then delete ), but even if I'd called free() and used the delete operator, "access violation" also happened. But , now attention! Sometimes it worked under Visual Studio, when I hadn't tried to alloc memory, and didn't worked , when I just launched an .exe file. Then I decided to check out what would happen without memory allocations, and it worked under VS and outside ( when I launched the .exe ). But when I removed all mem allocations from code to see what would happen, I also got "Access violation..." on the line
camera * c = new camera( Eye, At, Up, 0.5, Radius );
I have working solution under the Debug mode, and I decided to disable optimisations under Release, it worked under VS than and didn't work when I launched the .exe. I've tried everything and I don't know how to deal with this case. I've checked out again, I have no bad pointers. I've read something about memory leaks, but even if I 'd tried to delete or free() memory after my usage, it crashed anyway. I'm desperate.
Assuming that you already checked and debugged all possible pointer issues (I have a doubt), the most probable bug is unaligned DirectXMath.
XMVECTOR
andXMMATRIX
objects must be 16-byte aligned.Possible solutions are:
XMFLOATa
andXMFLOATaXb
(wherea
andb
are dimensions) as storage (class members, function parameters, etc.) and convert toXMMATRIX
andXMVECTOR
(placed on ctack) just before calculations#define _XM_NO_INTRINSICS_
before include file). It will disable alignment requirementProbably you will find this two answers useful: one, two
C++ notes (offtopic):
- Never mix
new
/free
,malloc
/delete
. You can not.- We tend to avoid all four of this in C++. Prefer to use smart pointers:
std::shared_ptr
,std::unique_ptr
, and their companion functions:std::make_shared
,std::make_unique()
- This is a memory leak (memory allocated for
cam
is lost forever after assignment and you cannot release it anymore):- Do instead:
- Global variables considered evil in C++- Raw pointers considered evil in C++
- Check The Definitive C++ Book Guide and List ("Best Practices" and "Intermediate" sections)
Hope it helps somehow. Happy coding!