Using XMVECTOR from DirectXMath as a class member

2019-02-19 18:19发布

问题:

I've been trying to use XMVECTOR as a class member for a bounding box, since I do a lot of calculations, but I use the XMFLOAT3 only once per frame, so the bounding box has a method that gives me it's center in a XMFLOAT3, otherwise it stays in a XMVECTOR;The class is delcared with __declspec(align(16)) and works in debug mode.However in Release mode it crashes the instant I set it to something:

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

Whenever I do:

Box A;

Box B;

A = B;

It crashes, giving me 0xC0000005: Access violation reading location 0x00000000. Also it crashes when I create it as a pointer:

Box* A = new Box();

This is the constructor:

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

Again, this works fine in Debug mode, but in Release it crashes.What could Release mode be changing that would generate invalid code?Do I need to do something else, other than aligning the box to 16 bytes?

回答1:

The class is not being created at an aligned address, so even though the XM* members are aligned on 16-byte boundaries, the parent's alignment miss-aligns them, causing the crash.

To prevent this you need to use _mm_alloc (which really just wraps _aligned_alloc), or replace the default allocator with one that returns blocks minimally aligned to 16 bytes (under x64 this the case with the default allocator).

a simple solution to this in C++ is to create a base class for all classes the contain XM* members that looks like the following:

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>
{
//...
};

As pointed out by @Dave, this is a minimal example, you'd want to overload all the new and delete operators, specifically new[] and delete[]