Question

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.

Was it helpful?

Solution

Assuming that you already checked and debugged all possible pointer issues (I have a doubt), the most probable bug is unaligned DirectXMath. XMVECTOR and XMMATRIX objects must be 16-byte aligned.

Possible solutions are:

  • Use aligned allocations
  • Do not use dynamic allocation (place objects on stack)
  • Use XMFLOATa and XMFLOATaXb (where a and b are dimensions) as storage (class members, function parameters, etc.) and convert to XMMATRIX and XMVECTOR (placed on ctack) just before calculations
  • Disable SSE intrinsics (put #define _XM_NO_INTRINSICS_ before include file). It will disable alignment requirement
  • Do not use DirectXMath (there are plenty other math libraries)

Probably 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):

cam = (camera*)malloc(sizeof(camera));
camera * c = new camera( Eye, At, Up, 0.5, Radius );
cam = c;

- Do instead:

std::shared_ptr<Camera> cam;
...
cam = std::make_shared<Camera>(Eye, At, Up, 0.5, Radius);
- 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!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top