【问题标题】:Can not access 16-bit aligned members of std::vector? [closed]无法访问 std::vector 的 16 位对齐成员? [关闭]
【发布时间】:2013-09-04 19:54:18
【问题描述】:

我正在为 C++ 中的 STL 向量而苦苦挣扎。我曾一度只为 x64 编译我的项目(实际上是几个月),一切正常,当我记得我也需要它在 x86 机器上工作(Win32 DirectX 应用程序)时。 当然,编译器错误立即出现,例如,如果传递给函数(即 XMVECTOR 和 XMMATRIX 以及 XMFLOATA 结构),则 16 位对齐的结构将不会对齐。我成功地解决了这些问题,并让我的程序再次运行,直到我尝试通过 push_back() 和 emplace_back() 将这些结构加载到 std::vectors 中。我给出一个简短的示例代码以便清楚:

struct Armature
{
string name;
int index;
//{...} There are much more
XMVECTOR translation; //Four 32 bit floating point components aligned on a 16 byte 
// boundary and mapped to hardware vector registers
XMVECTOR rotation;
XMVECTOR scale;
XMMATRIX world; //it is like 4 XMVECTORs (4*4 matrix)

Armature(){
//I initialize everything here
}
};

这是我的结构,我尝试将几个 Armature 加载到一个向量中,例如:

std::vector<Armature> armatures;

while(ThereAreMoreArmaturesToRead()){ //roughly like this, I just parse a file and load up the information from there to fill out my Armature structure
armatures.push_back( Armature() );
}

完整代码在这里:http://pastebin.com/6D1wF4Vh

我尝试将 __declspec_align(16) 设置为所有内容,尝试使用 Armature* 填充向量并在 new 运算符中执行 aligned_malloc,但 程序每次退出时都会出现访问冲突读取位置 0xFFFFFFF 有时在向量中。 h 在 push_back 函数上,有时在初始化 XMVECTOR 结构等时。

我在这里错过了一些微不足道的事情吗?那么,如果有人能指出显而易见的问题或提供任何帮助,我将不胜感激。

【问题讨论】:

  • 这非常不清楚。具体来说,您将 align(16) 应用于什么?什么是导致运行时错误的具体测试用例?
  • 我在提供的代码中没有看到__declspec_align(16)。您是要对齐整个 Armature 类型,还是对齐其中的特定字段?
  • @Oli Charlesworth 对不起,如果我让自己不清楚。我尝试首先将 align(16) 应用于我的结构,在我变得非常绝望之后,我尝试将其设置为其他所有可验证的。而且我不完全理解问题的第二部分,抱歉,我的测试用例是当我调用 armatures.push_back(Armature()) 时,它会在原始“vector.h”或我的 Armature struct 构造函数中随机崩溃当我想初始化一个 XMVECTOR 或 XMMATRIX 时。
  • 微软似乎建议您使用 XMFLOAT4 和 XMFLOAT4X4 来存储值,并使用 XMVECTOR 和 XMMATRIX 进行计算。我认为主要是因为这个问题。
  • @JánosTuránszki:这些文件都没有这个错误。 错误在您的代码中

标签: c++ vector stl directxmath


【解决方案1】:

Microsoft 似乎建议您使用 XMFLOAT4 和 XMFLOAT4X4 来存储值,并使用 XMVECTOR 和 XMMATRIX 进行计算。

来自 DirectXMath 帮助:(http://msdn.microsoft.com/en-us/library/windows/desktop/ee418725(v=vs.85).aspx#basic_usage)

“但是,避免在类或结构中直接使用 XMVECTOR 或 XMMATRIX 通常更容易、更紧凑。相反,使用 XMFLOAT3、XMFLOAT4、XMFLOAT4X3、XMFLOAT4X4 等作为结构的成员。此外,您可以使用 Vector Loading 和 Vector Storage 函数将数据有效地移动到 XMVECTOR 或 XMMATRIX 局部变量中,执行计算并存储结果。还有流式函数(XMVector3TransformStream、XMVector4TransformStream 等)可以直接有效地操作在这些数据类型的数组上。”

您可以存储 XMVECTOR 和 XMMATRIX 类型,但特别是如果您将它们存储在向量等中,则很难获得正确的对齐要求,因为默认分配器不满足要求。

【讨论】:

    【解决方案2】:

    while(!file.eof()) 不会做你认为的那样。 eof() 仅返回 true 试图读取文件末尾之后。在调用 push_back(...) 之前检查file 的错误状态吗?如果没有,最后一个元素将被初始化为未定义的值。并且根据您的软件,可能会也可能不会导致运行时错误。

    【讨论】:

    • 这显然不是问题,因为正如我所描述的,如果我为 x64 编译和运行该代码,它会运行得非常好。另外,我的程序中真正的 for 循环不是那样的,我只是创建它以便人们可以看到,该向量会有很多成员。
    • @JánosTuránszki 当您向我们展示不同的错误代码时,您希望我们如何找到您代码中的错误?
    • 循环与这件事无关,因为它只是在第一个 vector::push_back() 操作上崩溃。但我只是为你修改了它。
    • while(ThereAreMoreArmaturesToRead()) 没有按照您的想法执行 ;-) 您必须在使用您读取的值之前检查 file 的状态。这不仅会捕获过去 eof 的读取,还会捕获解析错误。
    • 看,最重要的是,我只加载任何内容,如果当前行以指定的字符串或字符开头,我会在开关中检查它。我什至已经上传了它:pastebin.com/6D1wF4Vh(感谢您的帮助!)
    猜你喜欢
    • 2021-02-26
    • 1970-01-01
    • 2018-05-02
    • 1970-01-01
    • 2022-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-06
    相关资源
    最近更新 更多