访问冲突和Visual Studio的异常行为 [英] Access violation and strange behavior of Visual Studio
问题描述
我正在DirectX11上编写一个测试应用程序,并且有2个类"Box"和"camera". 盒子"是要在屏幕上绘制的立方体,这是相机":
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);
} ;
我正在Visual Studio 2012中工作,并且一切都很完美,直到我决定在Release config下构建我的解决方案.相机构造函数始终在0x0附近的不同地址上出现未处理的异常:访问冲突读取位置..." .我知道为什么会发生这种情况,我已经检查了所有使用过的指针,但我完全不知道发生了什么.这是带有WinMain函数的文件的开头:
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()-一个函数,当所有崩溃时,我在其中调用构造函数:
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 是指向相机类的全局指针,请不要这样看我,这在VS下工作了一段时间.
cam is a global pointer to camera class, don't look at me that way, this worked under VS for some time.
如果我需要解析从lpCmdLine提取的命令行参数,则需要分配内存,并且我认为,原因是在..Main开头的内存分配.我使用了 malloc()和数组(先使用new然后使用delete),但是即使我调用了free()并使用了delete运算符,也发生了访问冲突".但是,现在注意!有时在Visual Studio下,当我没有尝试分配内存,而当我刚启动.exe文件时,却没有用.然后,我决定检查没有内存分配的情况会发生什么,并且它在VS和外部环境下都能正常工作(当我启动.exe时).但是,当我从代码中删除所有内存分配以查看会发生什么时,我也在线上看到访问冲突..."
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 );
我在Debug模式下有可行的解决方案,我决定在Release下禁用优化,它在VS下工作,而在启动.exe时不工作.我已经尝试了所有方法,但不知道如何处理此案.我再次签出,没有错误的指示.我已经读过一些有关内存泄漏的内容,但是即使在使用后尝试删除或 free()内存,该内存还是会崩溃.我很绝望.
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.
推荐答案
假定您已经检查并调试了所有可能的指针问题(我怀疑),最可能的错误是未对齐的DirectXMath. XMVECTOR
和XMMATRIX
对象必须对齐16个字节.
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.
可能的解决方案是:
- 使用统一分配
- 请勿使用动态分配(将对象放置在堆栈上)
- 使用
XMFLOATa
和XMFLOATaXb
(其中a
和b
是尺寸)作为存储(类成员,函数参数等)并转换为XMMATRIX
和XMVECTOR
(放在ctack上)在计算之前 - 禁用SSE内部函数(输入
- Use aligned allocations
- Do not use dynamic allocation (place objects on stack)
- Use
XMFLOATa
andXMFLOATaXb
(wherea
andb
are dimensions) as storage (class members, function parameters, etc.) and convert toXMMATRIX
andXMVECTOR
(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 ++注释(主题):
-切勿混用new
/free
,malloc
/delete
.你不能.
-我们倾向于在C ++中避免所有这四种情况.优先使用智能指针:std::shared_ptr
,std::unique_ptr
及其伴随函数:std::make_shared
,std::make_unique()
-这是内存泄漏(分配给cam
的内存在分配后会永远丢失,并且您无法再释放它):
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;
-改为:
std::shared_ptr<Camera> cam;
...
cam = std::make_shared<Camera>(Eye, At, Up, 0.5, Radius);
-全局变量在C ++中被认为是邪恶的
-在C ++中原始指针被认为是邪恶的
-检查权威的C ++书籍指南和列表(最佳做法"和中级"部分)
- 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!
这篇关于访问冲突和Visual Studio的异常行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!