如果在调试器中运行,数据在 Visual Studio 中未正确对齐

问题描述 投票:0回答:1

我与 SSE 合作已经有一段时间了,我也看到了一些一致性问题。然而,这超出了我的理解范围:

无论我是否 使用 F5(调试)运行程序或 我是否在调试器之外运行它 (Ctrl+F5)!

一些背景信息: 我正在使用支持 SSE 的数据类型的包装器 - 具有重载运算符和自定义分配器(使用

new
delete
重载
_mm_malloc
_mm_free
运算符)。但在下面的示例中,我成功地进一步减少了问题,即即使我不使用自定义分配器,问题也会发生。

如下所示,在 main() 中,我在堆上动态分配了一个 TestClass 对象,其中包含一个 SSEVector 类型的对象。我正在使用虚拟

float[2]
成员变量来稍微“错位”堆栈。

当我使用 F5 运行时,我获得以下输出:

object address 00346678
_memberVariable1 address 00346678
_sseVector address 00346688

如果我使用 Ctrl+F5 运行:

object address 00345B70
_memberVariable1 address 00345B70
_sseVector address 00345B80

如您所见,当我在调试器中运行它时,对齐方式是不同的(即不是 16 字节)。使用 Ctrl-F5 时对齐正确只是巧合吗?我正在将 Visual Studio 2010 与新项目一起使用(默认设置)。

如果我在堆栈上声明对象,即

TestClass myObject;
,则不会出现此问题。使用
__declspec(align(16))
也没有帮助。

我用来重现问题的代码:

#include <iostream>
#include <string>
#include <xmmintrin.h>  // SSE
//#include "DynAlignedAllocator.h"

//////////////////////////////////////////////////////////////
class SSEVector /*: public DynAlignedAllocator<16>*/
{
public:
    SSEVector() { }

    __m128 vec;
};

class TestClass
{
public:
    TestClass() { }

    /*__declspec(align(16))*/ float _memberVariable1 [2];
    SSEVector _sseVector;
};

//////////////////////////////////////////////////////////////
int main (void)
{
    TestClass* myObject = new TestClass;

    std::cout << "object address " << myObject << std::endl;
    std::cout << "_memberVariable1 address " << &(myObject->_memberVariable1) << std::endl;
    std::cout << "_sseVector address " << &(myObject->_sseVector) << std::endl;

    delete myObject;

    // wait for ENTER
    std::string dummy;
    std::getline(std::cin, dummy);

    return 0;
}

非常感谢任何提示或评论。预先感谢。

c++ visual-studio alignment sse
1个回答
5
投票

在调试器下运行时,您正在使用调试堆,这可能会影响对齐。

在您的环境设置中设置

_NO_DEBUG_HEAP=1
,看看这是否有帮助。

参见例如http://msdn.microsoft.com/en-us/library/aa366705%28v=vs.85%29.aspx

但是,使用 malloc 或 new 分配时不能保证对齐。在 VS 中解决这个问题的“正确”方法是使用

_aligned_malloc

当您希望 SSEVector 作为另一个结构体的成员时,您需要更改该结构体的 packing(使用 #pragma pack),或 SSEVector 的 __declspec(align)。

参见 align 如何与数据打包一起工作

您的情况发生的是(除了看似巧合的调试器/非调试器差异):

SSEVector
被声明为未对齐。如果直接使用
_aligned_malloc
分配它,它就会对齐。
TestClass
也是未对齐的,并使用默认包装。如果您使用
_aligned_malloc
分配它,则
TestClass
实例将正确对齐。这对您没有任何帮助,因为您希望
SSEVector
成员变量 对齐。

使用

SSEVector
__declspec(align)
上添加对齐要求将告诉编译器
SSEVector
堆栈变量必须对齐,并且作为结构体成员的
SSEVector
必须在结构/类内对齐。现在,如果您使用
TestClass
分配
_aligned_malloc
,它将正确对齐。由于 declspec,结构中的
SSEVector
偏移量也正确对齐,因此 SSEVector 的绝对地址对于您的使用来说是正确的。

© www.soinside.com 2019 - 2024. All rights reserved.