如果在调试器中运行,则数据在 Visual Studio 中无法正确对齐
我与 SSE 合作已经有一段时间了,我也看到了一些一致性问题。然而,这超出了我的理解范围:
无论我是否 使用 F5(调试)运行程序或 我是否在调试器之外运行它 (Ctrl+F5)!
一些背景信息: 我正在使用支持 SSE 的数据类型的包装器 - 具有重载运算符和自定义分配器(使用 _mm_malloc
和 < 重载 new
和 delete
运算符代码>_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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在调试器下运行时,您正在使用调试堆,这可能会影响对齐。
在环境设置中设置
_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
, theTestClass
instance will be properly aligned. This doesn't help you at all, since you want theSSEVector
member variable to be aligned.Adding an alignment requirement on
SSEVector
using__declspec(align)
will tell the compiler thatSSEVector
stack variables must be aligned, and thatSSEVector
as a struct member must be aligned within the struct/class. Now, if you allocate aTestClass
using_aligned_malloc
, it will be properly aligned. And theSSEVector
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.