重要な情報:
問題:
IDEを使用して静的ライブラリプロジェクトをコンパイルすると、次の警告が表示されます。
warning C4316: ... : object allocated on the heap may not be aligned 16
私は単にこの警告を無視することができます...しかし私はそれが理由でそこにあると仮定していて、少なくともそれが何を意味するのか、そしてそれが将来どのような影響を与える可能性があるのかを理解したいと思います。
このコード行は問題に関連していると思いますこれはWin32ウィンドウラッパークラス内で呼び出されます:
m_direct3D = new Direct3D(this);
m_direct3Dは、Direct3Dラッパークラスへのポインターです。
これがラッパーのヘッダーファイルです(トリミングが必要なことは認めます):
#pragma once
// Windows
#include <d3d11.h>
#include <DirectXMath.h>
// Standard
#include <stdint.h>
#include <vector>
// JGlib
#include "Window.h"
namespace JGlib
{
namespace Graphics
{
class Direct3D
{
public:
// Construtor and destructor
Direct3D(const JGlib::Graphics::Window* window);
~Direct3D();
// Public methods
void Initialise();
void BeginDraw();
void Draw();
void EndDraw();
private:
// Private methods
// Private member variables
const Window* m_window;
ID3D11Device* m_device;
IDXGIAdapter* m_adapter;
DXGI_ADAPTER_DESC m_adapterDescription;
uint32_t m_videoCardMemory;
IDXGIFactory* m_factory;
IDXGIOutput* m_monitor;
DXGI_MODE_DESC* m_displayModes;
uint32_t m_numberOfModes;
DXGI_RATIONAL m_refreshRate;
DXGI_SWAP_CHAIN_DESC m_swapChainDescription;
D3D_FEATURE_LEVEL m_featureLevel;
ID3D11DeviceContext* m_deviceContext;
IDXGISwapChain* m_swapChain;
ID3D11Texture2D* m_backBuffer;
ID3D11RenderTargetView* m_renderTargetView;
ID3D11Texture2D* m_depthStencilBuffer;
D3D11_TEXTURE2D_DESC m_depthBufferDescription;
D3D11_DEPTH_STENCIL_DESC m_depthStencilDescription;
ID3D11DepthStencilState* m_depthStencilState;
ID3D11DepthStencilView* m_depthStencilView;
D3D11_RASTERIZER_DESC m_rasterDescription;
D3D11_VIEWPORT m_viewport;
float m_fieldOfView;
float m_screenAspectRatio;
ID3D11RasterizerState* m_rasterState;
DirectX::XMMATRIX m_projectionMatrix;
DirectX::XMMATRIX m_worldMatrix;
DirectX::XMMATRIX m_orthographicMatrix;
float m_screenDepth;
float m_screenNear;
};
}
}
問題をグーグルで調べてみましたが、ほとんど情報が見つかりませんでした。私が見つけた情報は理解できませんでした。
結論として、私は次のことを求めています:
追加情報:
Visual Studioの構成マネージャーをx64用にコンパイルするように変更した場合、この問題は発生しません。
C4316はどういう意味ですか?
C4316はエラーコードです。これは、簡単に見つけられるようにする一意の識別子です ドキュメント 。
私のコードでそれを引き起こしているのは何ですか?
_DirectX::XMMATRIX
_クラスの使用法。そのクラスのインスタンスは、16バイト境界で整列する必要があります。コンパイラは、スタックまたはグローバルスコープで_JGLib::Graphics::Direct3D
_インスタンスを作成するたびに、それが適切に整列されることを確認しますが、ヒープにインスタンスを動的に割り当てる場合、コンパイラはオブジェクトがそうすることを保証できません。 malloc()
とその仲間は通常、8バイトのアラインメントしか保証しないため、適切にアラインメントされます。
私がそれを無視した場合、これは将来どのような影響を与える可能性がありますか?
[〜#〜] sse [〜#〜] 命令が不整合なデータを操作しているため、これらのマトリックスインスタンスにアクセスすると、コードがクラッシュする可能性があります。
この警告が表示される原因となっている問題を「修正」するにはどうすればよいですか?
ドキュメントが示唆しているように、16バイトのアラインメントを保証するには、クラスの_operator new
_と_operator delete
_をオーバーライドする必要があります。 _aligned_malloc()
および _aligned_free()
を使用して、より大きな配置に配置されたメモリを割り当てて解放できます。
次のように、new演算子とdelete演算子をオーバーライドする必要があります。
__declspec(align(16)) class MyClass
{
public:
DirectX::XMMATRIX m_projectionMatrix;
virtual ~MyClass()
{
}
void* operator new(size_t i)
{
return _mm_malloc(i,16);
}
void operator delete(void* p)
{
_mm_free(p);
}
};
前処理されたコードを見ると、おそらくそこにこの__declspec(align(16))
のようなものがあり、new
がその制約で整列されない可能性がある一方で、16バイトで整列するように要求します。 http://msdn.Microsoft.com/en-us/library/vstudio/dn448573.aspx に準拠すると、Override operator new and operator delete for over-aligned types so that they use the aligned allocation routines—for example, _aligned_malloc and _aligned_free.
で修正できます。
_DirectX::XMMATRIX
_にはSSEデータが含まれている(このため__declspec(align(16)
)でマークされている)ため、16B境界に揃える必要があります。そうしないと、それにアクセスする命令がアクセス違反を引き起こします。
警告は、オペレーターnewによって返されるメモリーが16Bに整列されているという保証がないことを示しています。
代わりに、オブジェクトをグローバル変数またはローカル変数として作成できますか?このようにして、コンパイラーはアライメントを強制できます。できない場合は、 _ aligned_malloc および _ aligned_free を使用して実装された_Direct3D
_クラスにオーバーロードされたnew
およびdelete
を提供できます。