警告C4316:堆上分配的对象可能未对齐16

时间:2013-11-20 19:11:23

标签: c++ compiler-errors visual-studio-2013

重要信息:

  • 开发操作系统:Windows 8.1 64位
  • 目标操作系统:Windows 8.1 64位
  • 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. 如何“修复”导致此警告出现的问题?
  5. 其他信息:

    当我将Visual Studio的配置管理器更改为x64编译时,不会发生此问题。

4 个答案:

答案 0 :(得分:27)

  

C4316是什么意思?

C4316是错误代码。它是一个唯一标识符,可以轻松找到the documentation

  

我的代码中导致它的原因是什么?

DirectX::XMMATRIX类的用法。该类的实例必须在16字节边界上对齐。编译器确保无论何时在堆栈或全局范围内创建JGLib::Graphics::Direct3D实例,它都会正确对齐它,但如果在堆上动态分配实例,则编译器无法保证对象将在正确对齐,因为malloc()和朋友通常只保证8字节对齐。

  

如果我忽略它会对未来产生什么影响?

由于SSE指令操作未对齐的数据,因此访问这些矩阵实例时,您的代码可能会崩溃。

  

如何“修复”导致出现此警告的问题?

正如文档所示,您需要覆盖类operator newoperator delete,以保证16字节对齐。您可以使用_aligned_malloc()_aligned_free()分配和释放在较大路线上对齐的内存。

答案 1 :(得分:17)

您需要覆盖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);
    }
};

答案 2 :(得分:4)

如果查看预处理代码,您可能会在其中找到类似__declspec(align(16))的内容,请求以16字节对齐,而new可能不会在该约束处对齐。根据{{​​3}},您可以按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.

修复此问题

答案 3 :(得分:4)

DirectX::XMMATRIX包含SSE数据(并因此而标记为__declspec(align(16)),因此需要在16B边界上对齐,否则访问它的指令将导致访问冲突。

警告告诉您,操作员new返回的保证内存不是16B对齐。

您可以将对象创建为全局或局部变量吗?这样编译器就可以强制执行对齐。如果您不能,则可以为使用_aligned_malloc_aligned_free实施的new课程提供超载的deleteDirect3D