【问题标题】:Using XMVECTOR from DirectXMath as a class member causes a crash only in Release Mode?使用 DirectXMath 中的 XMVECTOR 作为类成员仅在发布模式下会导致崩溃?
【发布时间】:2013-04-01 23:10:04
【问题描述】:

我一直在尝试使用 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();
    }

同样,这在 Debug 模式下运行良好,但在 Release 中它崩溃了。Release 模式会发生什么变化而生成无效代码?除了将框对齐到 16 字节之外,我还需要做其他事情吗?

【问题讨论】:

  • 请注意,您不需要创建Box 类。 DirectXMath 包含 BoundingBox 已经在 DirectXCollision.h 标头中。

标签: c++ simd release-mode directxmath


【解决方案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 所指出的,这是一个最小的示例,您需要重载所有 newdelete 运算符,特别是new[]delete[] p>

【讨论】:

  • 所以我不再需要 declspec align 了吗?他们不应该做同样的事情吗?还是 _mm_alloc 专门用于具有 __m128 成员的类?
  • @DEIMOS:取自 __declspec(align()) 的 MSDN 页面: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. 因此,它只会影响编译器可以控制的分配,例如堆栈和堆栈变量,以及结构/class 偏移对齐。 _mm_malloc & _aligned_malloc 返回正确分配的数据,_mm_malloc 是 SSE 类型的宏简写。
  • 另请参阅msdn.microsoft.com/en-us/library/windows/desktop/… 的类型使用指南,了解有关 xmmath 的此主题的另一个讨论。
  • 您可能还需要数组运算符 [] 来使这个正确。我知道我最终需要它们;此外,如果您使用的是 DXUT,请记住,如果您使用的是他们的 GUI,它将使用您的分配器在您的代码(来自标头)中分配数组,然后在自己的代码中释放它们;因此,您必须将所有 4 个运算符放在 DXUT.h 中才能正常互操作。
  • 如果您是 DirectXMath 的新手,您应该考虑在 DirectX Tool Kit 中使用 SimpleMath 包装器,它可以透明地为您处理对齐问题。
猜你喜欢
  • 1970-01-01
  • 2017-06-13
  • 2020-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-17
  • 1970-01-01
相关资源
最近更新 更多