【问题标题】:Crash after m = XMMatrixIdentity() - alignment memory in classes?m = XMMatrixIdentity() 后崩溃 - 类中的对齐内存?
【发布时间】:2018-03-17 20:04:54
【问题描述】:

我正在查看 DirectX SDK 中的教程。教程 5 工作正常,但是在我将代码复制并分离到我自己的类之后,我在启动我的应用程序时遇到了奇怪的错误。

该行是:

g_World1 = XMMatrixIdentity();

因此,我在 xnamathmatrix.int operator= 中出现错误,如下所示:

XMFINLINE _XMMATRIX& _XMMATRIX::operator=
(
    CONST _XMMATRIX& M
)
{
    r[0] = M.r[0];
    r[1] = M.r[1];
    r[2] = M.r[2];
    r[3] = M.r[3];
    return *this;
}

错误信息是:

Access violation reading location 0xffffffff

我在某处读到它可能是由连接到 XMFLOAT4X4 / XMMATRIX 的东西引起的:

您是否考虑过使用 XMFLOAT4X4 来存储矩阵,并且只使用 XMMATRIX?

但我想我已经在使用 XMMATRIX。

MyClass.h:

private:
    XMMATRIX g_World1;

MyClass.cpp:

void init(){
   g_World1 = XMMatrixIdentity();
}

我认为我不应该更改 XMMATRIX g_World1;到 XMFLOAT4X4 g_World1,因为它会产生如下错误:

错误 C2679:二进制“=”:未找到采用“XMMATRIX”类型右侧操作数的运算符(或没有可接受的转换)

【问题讨论】:

    标签: c++ matrix directx sse xna-math-library


    【解决方案1】:

    由于 XMMATRIX 表示一个 16 字节对齐的 4x4 矩阵,因此 g_World1 的未对齐分配导致访问冲突(简单地说,g_World1 的地址不能被 16 整除)。

    某种解决方案:使结构成员对齐 16 个字节(以便 MyClass 将 g_World1 “就位”)。但是您仍然必须确保 MyClass 实例位于可被 16 整除的地址。

    您可以使用放置“new”运算符来分配 MyClass 对象。

    关于对齐见这里:How to align pointer

    【讨论】:

    • 也许这是一个愚蠢的问题,但如何实现呢?我制作了一个包含四个矩阵(视图、世界等)的结构矩阵,但是如何为它“启用 16 个字节的结构成员对齐”?
    • 对于 VStudio:项目属性 -> 配置属性 -> C/C++ -> 代码生成 -> 结构成员对齐 -> 那里选择 16
    • 对于 GCC,结构有一个“属性 ((aligned (16)))”
    • 维克多·拉蒂波夫,谢谢。我已经为 VStudio 做了,但我仍然有同样的错误。
    • 您还可以使用 DirectX Tool Kit 中的 SimpleMath 包装器类型,它们会自动为您执行加载/存储。
    【解决方案2】:

    XMVECTOR 和 XMMATRIX 是“注册代理”类型。您可以安全地将它们用作 Xbox 360、Xbox One 和 Windows x64 平台的类型,因为它们在堆栈上和在堆上分配的数据本身都具有 16 字节对齐。

    将它们用于 Windows 32 位或 Windows RT/ARM 需要更多努力,因为本机对齐小于 16 字节。一种方法是 DirectX Tool Kit 使用的技术……它使用 pImpl 习惯用法,并且 pImpl 内部类显式分配了 16 字节对齐,这是直接使用 XMVECTOR 和 XMMATRIX 类型的地方。另一种方法是使用所有各种“存储”类型,例如 XMFLOAT4 和 XMFLOAT4X4。

    注意:DirectXMath programmer's guide 涵盖了这一点。这不是一篇很长的文档,而且包含很多提示和建议。

    PS:MSDN 代码库上有一个 Win32 桌面标准 Direct3D 教程版本,不需要 DirectX SDK...它只使用 VS 2012 或 VS 2013 中包含的 Windows 8.x SDK。enter link description here

    【讨论】:

      【解决方案3】:

      谢谢。

      最后我决定使用 XMLoadFloat4x4() 和 XMStoreFloat4x4() 函数。我将类的成员存储为 Float4x4,并在每个 render() 循环中将它们转换为 XMMATRIX 以供临时使用。 但是......这是一个快速或愚蠢的解决方案?

      【讨论】:

      • 考虑开始另一个问题,这不是一个讨论论坛。如果矩阵的数量很少,这将不是问题。
      • 看起来他们是平等的。当然,如果您不将它们转换为 XMMatrix 进行计算(笑)。
      【解决方案4】:

      在“Frank D. Luna”的“Directx 11 3D 游戏编程简介”一书中说:

      不要将 XMMATRIX 用作类或结构的成员。始终使用 XMFloat4x4 并在需要时加载并存储回来。

      【讨论】:

        猜你喜欢
        • 2019-08-11
        • 2019-07-02
        • 2013-02-02
        • 2012-01-28
        • 2010-12-29
        • 2011-09-25
        • 2017-11-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多