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

发布于 2024-10-21 03:31:01 字数 1976 浏览 1 评论 0原文

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

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

一些背景信息: 我正在使用支持 SSE 的数据类型的包装器 - 具有重载运算符和自定义分配器(使用 _mm_malloc 和 < 重载 newdelete 运算符代码>_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;
}

非常感谢任何提示或评论。提前致谢。

I've been working with SSE for a while now, and I've seen my share of alignment issues. This, however, is beyond my understanding:

I get different alignment whether I
run the program using F5 (debug) or
whether I run it outside the debugger
(Ctrl+F5)!

Some background info:
I'm using a wrapper for a SSE-enabled datatype - with overloaded operators and custom allocator (overloadednew and delete operators using _mm_malloc and _mm_free). But in the example below, I've managed to reduce to problem even further, i.e. the issue also happens even if I don't use the custom allocator.

As you can see below, in main() I dynamically allocate a TestClass object on the heap, which contains a SSEVector type object. I'm using a dummy float[2] member variable to "missalign" the stack a bit.

I obtain the following output when I run with F5:

object address 00346678
_memberVariable1 address 00346678
_sseVector address 00346688

And if I run with Ctrl+F5:

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

As you can see, the alignment is different (i.e. not 16-byte) when I run it in the debugger. Is it just a coincidence that the alignment is correct when using Ctrl-F5? I'm using Visual Studio 2010 with a new project (default settings).

If I declare the object on the stack, i.e. TestClass myObject;, this issue does not appear. Using __declspec(align(16)) does not help, either.

The code I used to reproduce the issue:

#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;
}

Any hints or commentaries are greatly appreciated. Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

死开点丶别碍眼 2024-10-28 03:31:01

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

在环境设置中设置 _NO_DEBUG_HEAP=1,看看这是否有帮助。

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

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

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

请参阅align 如何与数据打包配合使用

在您的情况下会发生什么(除了看似巧合的调试器/非调试器差异):

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

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

When running under the debugger, you're using the debug heap, which may affect alignment.

Set _NO_DEBUG_HEAP=1 in your environment settings, and see if this helps.

See e.g. http://msdn.microsoft.com/en-us/library/aa366705%28v=vs.85%29.aspx

However, alignment is not guaranteed when allocating with malloc or new. The "correct" way of solving this in VS is to use _aligned_malloc.

When you want your SSEVector as a member of another structure, you need to change the packing of this structure (using #pragma pack), or the __declspec(align) of SSEVector.

See How align works with data packing

What happens in your cases are (apart from the seemingly coincidental debugger/non-debugger difference):

SSEVector is declared unaligned. If you allocate it directly using _aligned_malloc, it'll be aligned. TestClass is also unaligned, and uses default packing. If you allocate it using _aligned_malloc, the TestClass instance will be properly aligned. This doesn't help you at all, since you want the SSEVector member variable to be aligned.

Adding an alignment requirement on SSEVector using __declspec(align) will tell the compiler that SSEVector stack variables must be aligned, and that SSEVector as a struct member must be aligned within the struct/class. Now, if you allocate a TestClass using _aligned_malloc, it will be properly aligned. And the SSEVector offset in the struct is also properly aligned due to the declspec, so the absolute address of the SSEVector will be correct for your use.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文