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

Using XMVECTOR from DirectXMath as a class member causes a crash only in Release Mode?

本文关键字:模式 布模式 崩溃 XMVECTOR 中的 DirectXMath 成员 使用      更新时间:2023-10-16

我一直在尝试使用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字节外,我还需要做其他事情吗?

类不是在一个对齐的地址上创建的,所以即使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所指出的,这是一个最小的例子,您希望重载所有 newdelete操作符,特别是new[]delete[]