VisualStudio2015でDirectX11のプログラミングをしている。DirectXMath.hのXMATRIXを使おうと、このファイルをincludeし、変数宣言した途端、C4316エラーが発生した。このエラーへの原因と対処をまとめておく。
##原因
DirectXMath.hのXMATRIXクラスを使おうと、変数宣言した途端発生した。XMMATRIXクラスは以下のように16バイト単位のメモリアライメントが定義されている。
__declspec(align(16)) struct XMMATRIX {
VisualStudioが提供する標準の new/delete は8バイト境界だ。このため、このXMMATRIX使うクラスも16バイト単位のメモリアライメントで生成しなければならない。つまり、new/deleteをオーバーライドする必要がある。
##対処
前述の通り、XMMATRIXを保持・使用するクラスにて、以下のようにnew/delete関数をオーバーライドする。 _mm_malloc / _mm_free関数は、内部で _aligned_malloc / _aligned_free関数を呼び出している。
class CHogeHoge {
//16byte memory alignemt.
DirectX::XMMATRIX m_matrix;
//override the operator new/delete.
void* operator new( size_t i ) {
return _mm_malloc(i,16);
}
void operator delete( void* p ) {
_mm_free(p);
}
}
##より良い対処
以下のような テンプレートを使った AlignedAllocationPolicyクラスを作り、16バイトメモリアライメントが必要なクラスので使うと、同じコードを各クラスに書く手間が省ける。
#pragma once
template <size_t T>
class AlignedAllocationPolicy {
public:
static void* operator new( size_t i ) {
return _mm_malloc(i,T);
}
static void operator delete( void* p ) {
_mm_free(p);
}
};
使い方はこうだ。
class CHogeHoge : public AlignedAllocationPolicy<16> {
//16byte memory alignemt.
DirectX::XMMATRIX m_matrix;
};
##まとめ
DirectXMath.hのDirectX::XMMATRIXは、SSE命令を使い行列を高速に処理するために、16バイトメモリアライメントになっている。そのため使う側もそれに応じたコードを書かなければならない。面倒くさいけど仕方ないね。
参考:
alignemt error(C4316) 韓国語
warning C4316: object allocated on the heap may not be aligned 16.