Използването на XMVECTOR от DirectXMath като член на клас причинява срив само в режим на издаване?

Опитвам се да използвам XMVECTOR като член на класа за ограничителна кутия, тъй като правя много изчисления, но използвам XMFLOAT3 само веднъж на кадър, така че ограничителната кутия има метод, който ми дава, че е център в XMFLOAT3 , в противен случай той остава в XMVECTOR; Класът е decared с __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();
    }

Отново това работи добре в режим Debug, но в Release се срива. Какво може да се промени в Release mode, което би генерирало невалиден код? Трябва ли да направя нещо друго, освен да подравня полето към 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 align? Не трябва ли да правят същото? Или _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, имайте предвид, че ако използвате техния GUI, той ще направи разпределения на масиви във ВАШИЯ код (от заглавките), използвайки вашия разпределител и след това ще ги освободи в собствения си код; следователно трябва да поставите всичките 4 оператора в DXUT.h, за да може това да взаимодейства правилно. - person Dave; 24.07.2015
comment
Ако не сте запознати с DirectXMath, трябва да обмислите използването на обвивката SimpleMath в DirectX Tool Kit, който прозрачно се справя с проблемите с подравняването вместо вас. - person Chuck Walbourn; 05.08.2015