访问冲突和Visual Studio的异常行为 [英] Access violation and strange behavior of Visual Studio

查看:144
本文介绍了访问冲突和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. XMVECTORXMMATRIX对象必须对齐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.

可能的解决方案是:

  • 使用统一分配
  • 请勿使用动态分配(将对象放置在堆栈上)
  • 使用XMFLOATaXMFLOATaXb(其中ab是尺寸)作为存储(类成员,函数参数等)并转换为XMMATRIXXMVECTOR(放在ctack上)在计算之前
  • 禁用SSE内部函数(输入
  • 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 ++注释(主题):
-切勿混用new/freemalloc/delete.你不能.
-我们倾向于在C ++中避免所有这四种情况.优先使用智能指针:std::shared_ptrstd::unique_ptr及其伴随函数:std::make_sharedstd::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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆