Предупреждение C4316: объект, выделенный в куче, может быть не выровнен 16
Важная информация:
- Разработка ОС: 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
Я мог бы просто проигнорировать это предупреждение... но я предполагаю, что оно есть по какой-то причине и хотел бы хотя бы понять, что это значит и какие последствия это может иметь в будущем.
Я считаю, что эта строка кода связана с проблемой, которая вызывается в моем классе оболочки Windows 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;
};
}
}
Я попытался погуглить вопрос, но нашел мало информации. Информацию, которую я нашел, я не понял.
В заключение я прошу следующее:
- Что означает C4316?
- Что вызывает это в моем коде?
- Какие последствия это может иметь в будущем, если я проигнорирую это?
- Как мне "исправить" проблему, из-за которой появляется это предупреждение?
Дополнительная информация:
Когда я изменил диспетчер конфигурации Visual Studio для компиляции для x64, эта проблема не возникала.
4 ответа
Что означает C4316?
C4316- это код ошибки. Это уникальный идентификатор, который облегчает поиск документации.
Что вызывает это в моем коде?
Использование DirectX::XMMATRIX
учебный класс. Экземпляры этого класса должны быть выровнены по 16-байтовым границам. Компилятор гарантирует, что всякий раз, когда вы создаете JGLib::Graphics::Direct3D
экземпляр в стеке или в глобальной области видимости, он будет правильно выровнен, но если вы динамически выделяете экземпляр в куче, компилятор не может гарантировать, что объект будет правильно выровнен, потому что malloc()
а друзья обычно гарантируют только 8-байтовое выравнивание.
Какие последствия это может иметь в будущем, если я проигнорирую это?
Ваш код может дать сбой при доступе к этим экземплярам матрицы из-за инструкций SSE, работающих с смещенными данными.
Как мне "исправить" проблему, из-за которой появляется это предупреждение?
Как видно из документации, вам нужно переопределить класс operator new
а также operator delete
чтобы гарантировать 16-байтовое выравнивание. Ты можешь использовать _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))
там, запрашивая выравнивание на 16 байтов в то время как new
может не выравниваться при этом ограничении. Согласно 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.
Можете ли вы создать объект как глобальную или локальную переменную? Таким образом, компилятор может обеспечить выравнивание. Если вы не можете, вы можете предоставить перегруженный new
а также delete
для тебя Direct3D
класс реализован с использованием _aligned_malloc и _aligned_free.