我正在DirectX11上编写测试应用程序,我有2个类“Box”和“camera”。 “Box”是一个要在屏幕上绘制的立方体,这是“相机”:
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);
} ;
我在Visual Studio 2012中工作,一切都很完美,直到我决定在Release config下构建我的解决方案。相机构造函数始终位于0x0附近的不同地址上的“未处理的异常:访问违规读取位置......”。我知道为什么会发生这种情况,我已经检查了我使用的所有指针,而且我完全不明白,发生了什么。这是具有WinMain函数的文件的开头:
#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() - 一个函数,我调用构造函数,当所有崩溃时:
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 是一个指向相机类的全局指针,不要那样看我,这在VS下工作了一段时间。
如果我需要解析来自lpCmdLine的命令行参数,我需要分配内存,我想,原因是在..Main开头的内存分配。我使用 malloc()和数组(使用new然后删除),但即使我调用了free()并使用了delete运算符,也会发生“访问冲突”。但是,现在关注!有时它在Visual Studio下工作,当我没有尝试分配内存,并且当我刚刚启动.exe文件时没有工作。然后我决定查看没有内存分配会发生什么,它在VS和外部工作(当我启动.exe时)。但是当我从代码中删除所有内存分配以查看会发生什么时,我还在线路上获得了“访问冲突...”
camera * c = new camera( Eye, At, Up, 0.5, Radius );
我在调试模式下有工作解决方案,我决定在Release下禁用优化,它在VS下运行比在启动.exe时不起作用。我已经尝试了一切,我不知道如何处理这个案子。我再次检查,我没有坏指针。我已经阅读了一些有关内存泄漏的内容,但即使我在使用后尝试删除或 free()内存,它仍然会崩溃。我很绝望。
答案 0 :(得分:2)
假设您已经检查并调试了所有可能的指针问题(我有疑问),最可能的错误是未对齐的DirectXMath。 XMVECTOR
and XMMATRIX
objects must be 16-byte aligned
可能的解决方案是:
XMFLOATa
和XMFLOATaXb
(其中a
和b
为维度)作为存储(类成员,函数参数等)并转换为{{1}和计算前的XMMATRIX
(放在ctack上)#define _XM_NO_INTRINSICS_
)。它将禁用对齐要求
C ++笔记(offtopic):
- 永远不要混用XMVECTOR
/ new
,free
/ malloc
。你不能。
- 我们倾向于在C ++中避免所有这四个。更喜欢使用智能指针:delete
,std::shared_ptr
及其配套功能:std::unique_ptr
,std::make_shared
- 这是内存泄漏(分配给std::make_unique()
的内存在分配后永远丢失,你不能再发布它了):
cam = (camera*)malloc(sizeof(camera)); camera * c = new camera( Eye, At, Up, 0.5, Radius ); cam = c;
- 改为:
std::shared_ptr<Camera> cam; ... cam = std::make_shared<Camera>(Eye, At, Up, 0.5, Radius);- 在C ++中被认为是邪恶的全局变量
希望它有所帮助。 快乐的编码!