web-dev-qa-db-ja.com

警告C4316:ヒープに割り当てられたオブジェクトが整列されていない可能性があります16

重要な情報:

  • 開発OS:Windows 8.164ビット
  • ターゲットOS:Windows 8.164ビット
  • IDE:Visual Studio 2013 Professional
  • 言語:C++

問題:

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;
        };
    }
}

問題をグーグルで調べてみましたが、ほとんど情報が見つかりませんでした。私が見つけた情報は理解できませんでした。

結論として、私は次のことを求めています:

  1. C4316はどういう意味ですか?
  2. 私のコードでそれを引き起こしているのは何ですか?
  3. 私がそれを無視した場合、これは将来どのような影響を与える可能性がありますか?
  4. この警告が表示される原因となっている問題を「修正」するにはどうすればよいですか?

追加情報:

Visual Studioの構成マネージャーをx64用にコンパイルするように変更した場合、この問題は発生しません。

18
OMGtechy

C4316はどういう意味ですか?

C4316はエラーコードです。これは、簡単に見つけられるようにする一意の識別子です ドキュメント

私のコードでそれを引き起こしているのは何ですか?

_DirectX::XMMATRIX_クラスの使用法。そのクラスのインスタンスは、16バイト境界で整列する必要があります。コンパイラは、スタックまたはグローバルスコープで_JGLib::Graphics::Direct3D_インスタンスを作成するたびに、それが適切に整列されることを確認しますが、ヒープにインスタンスを動的に割り当てる場合、コンパイラはオブジェクトがそうすることを保証できません。 malloc()とその仲間は通常、8バイトのアラインメントしか保証しないため、適切にアラインメントされます。

私がそれを無視した場合、これは将来どのような影響を与える可能性がありますか?

[〜#〜] sse [〜#〜] 命令が不整合なデータを操作しているため、これらのマトリックスインスタンスにアクセスすると、コードがクラッシュする可能性があります。

この警告が表示される原因となっている問題を「修正」するにはどうすればよいですか?

ドキュメントが示唆しているように、16バイトのアラインメントを保証するには、クラスの_operator new_と_operator delete_をオーバーライドする必要があります。 _aligned_malloc() および _aligned_free() を使用して、より大きな配置に配置されたメモリを割り当てて解放できます。

27
Adam Rosenfield

次のように、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);
    }
};
17
aguaviva

前処理されたコードを見ると、おそらくそこにこの__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.で修正できます。

4
Mark B

_DirectX::XMMATRIX_にはSSEデータが含まれている(このため__declspec(align(16))でマークされている)ため、16B境界に揃える必要があります。そうしないと、それにアクセスする命令がアクセス違反を引き起こします。

警告は、オペレーターnewによって返されるメモリーが16Bに整列されているという保証がないことを示しています。

代わりに、オブジェクトをグローバル変数またはローカル変数として作成できますか?このようにして、コンパイラーはアライメントを強制できます。できない場合は、 _ aligned_malloc および _ aligned_free を使用して実装された_Direct3D_クラスにオーバーロードされたnewおよびdeleteを提供できます。

4
Suma