Использование XMVECTOR из DirectXMath в качестве члена класса вызывает сбой только в режиме выпуска?

Я пытался использовать XMVECTOR в качестве члена класса для ограничивающей рамки, так как я делаю много вычислений, но я использую XMFLOAT3 только один раз за кадр, поэтому у ограничивающей рамки есть метод, который дает мне его центр в XMFLOAT3 , в противном случае он остается в XMVECTOR; класс удаляется с помощью __declspec(align(16)) и работает в режиме отладки. Однако в режиме выпуска происходит сбой в тот момент, когда я что-то устанавливаю:

    Box& Box::operator=(const Box& box)
    {
        _center = box._center;
        _extents = box._extents;
        return *this;
    }

Всякий раз, когда я делаю:

Box A;

Box B;

A = B;

Он вылетает, выдавая мне 0xC0000005: местоположение чтения нарушения доступа 0x00000000. Также он падает, когда я создаю его как указатель:

Box* A = new Box();

Это конструктор:

    Box::Box()
    {
        center = XMVectorZero();
        extents = XMVectorSplatOne();
    }

Опять же, это отлично работает в режиме отладки, но в режиме выпуска происходит сбой. Что может измениться в режиме выпуска, что приведет к созданию недопустимого кода? Нужно ли мне делать что-то еще, кроме выравнивания поля по 16 байтам?


person ulak blade    schedule 01.04.2013    source источник
comment
Обратите внимание, что вам не нужно создавать класс Box. DirectXMath включает BoundingBox уже в DirectXCollision.h заголовок.   -  person Chuck Walbourn    schedule 05.08.2015


Ответы (1)


Класс не создается по выровненному адресу, поэтому, хотя элементы XM* выровнены по 16-байтовым границам, выравнивание родителя нарушает их выравнивание, вызывая сбой.

Чтобы предотвратить это, вам нужно использовать _mm_alloc (который на самом деле просто обертывает _aligned_alloc) или замените распределитель по умолчанию на тот, который возвращает блоки, минимально выровненные по 16 байтам (в x64 это случай с распределителем по умолчанию).

простым решением этой проблемы в C++ является создание базового класса для всех классов, содержащих элементы XM*, который выглядит следующим образом:

template<size_t Alignment> class AlignedAllocationPolicy
{
    public:
    static void* operator new(size_t size)
    {
        return _aligned_malloc(size,Alienment);
    }

    static void operator delete(void* memory)
    {
        _aligned_free(memory);
    }
};

class MyAlignedObject : public AlignedAllocationPolicy<16>
{
//...
};

Как указал @Dave, это минимальный пример, вы хотите перегрузить все операторы new и delete, в частности new[] и delete[]

person Necrolis    schedule 01.04.2013
comment
так что мне больше не нужно выравнивание declspec? Разве они не должны делать то же самое? Или _mm_alloc специализирован для классов с членами __m128? - person ulak blade; 02.04.2013
comment
@DEIMOS: взято со страницы MSDN для __declspec(align()): Note that normal allocators, such as malloc, C++ operator new, and the Win32 allocators return memory that will most likely not be sufficiently aligned for __declspec(align(#)) structures or arrays of structures. Таким образом, это повлияет только на выделения, которыми управляет компилятор, такие как стек и переменные стека, а также выравнивание смещения структуры/класса. _mm_malloc и _aligned_malloc возвращают правильно распределенные данные, а _mm_malloc является сокращением макроса для типов SSE. - person Necrolis; 02.04.2013
comment
см. также Руководство по использованию типов по адресу msdn .microsoft.com/en-us/library/windows/desktop/ для другого обсуждения этой темы для xmmath. - person Yostage; 14.06.2013
comment
Вам также, вероятно, понадобятся операторы массива [], чтобы сделать это правильно. Я знаю, что нуждался в них; кроме того, если вы используете DXUT, имейте в виду, что если вы используете их графический интерфейс, он будет выделять массивы в ВАШЕМ коде (из заголовков), используя ваш распределитель, а затем освобождать их в своем собственном коде; таким образом, вы должны поместить все 4 оператора в DXUT.h для правильного взаимодействия. - person Dave; 24.07.2015
comment
Если вы новичок в DirectXMath, вам следует рассмотреть возможность использования оболочки SimpleMath в Набор инструментов DirectX, который прозрачно решает проблемы выравнивания за вас. - person Chuck Walbourn; 05.08.2015