使用DirectXMath中的XMVECTOR作为类成员仅在发布模式下导致崩溃?

ula*_*ade 2 c++ simd release-mode directxmath

我一直在尝试使用XMVECTOR作为边界框的类成员,因为我做了很多计算,但是每帧只使用一次XMFLOAT3,所以边界框有一个方法让我在XMFLOAT3中居中,否则它保留在XMVECTOR中;该类用__declspec(align(16))进行处理,并在调试模式下工作.但是在Release模式下,它崩溃了我设置的东西:

    Box& Box::operator=(const Box& box)
    {
        _center = box._center;
        _extents = box._extents;
        return *this;
    }
Run Code Online (Sandbox Code Playgroud)

每当我这样做:

Box A;

Box B;

A = B;
Run Code Online (Sandbox Code Playgroud)

它崩溃,给我0xC0000005:访问冲突读取位置0x00000000.当我将其创建为指针时,它也会崩溃:

Box* A = new Box();
Run Code Online (Sandbox Code Playgroud)

这是构造函数:

    Box::Box()
    {
        center = XMVectorZero();
        extents = XMVectorSplatOne();
    }
Run Code Online (Sandbox Code Playgroud)

再次,这在调试模式下工作正常,但在Release中它崩溃了.什么样的Release模式可以改变,会产生无效的代码?除了将盒子对齐到16个字节之外,我还需要做其他事情吗?

Nec*_*lis 6

该类不是在对齐的地址上创建的,因此即使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>
{
//...
};
Run Code Online (Sandbox Code Playgroud)

正如@戴夫指出,这是一个小例子,你会想重载所有newdelete运营商,特别是new[]delete[]

  • 有关xmmath的此主题的另一个讨论,请参阅http://msdn.microsoft.com/en-us/library/windows/desktop/ee418725(v=vs.85).aspx上的"类型使用指南". (2认同)