在执行一些现有代码的重写以更好地简化代码时,我在测试期间遇到了崩溃,我将其缩小为内存对齐问题,但是我不确定如何在不掩盖问题的情况下进行修复。是否有我可能需要的编译器原语。
我正在使用Microsoft Visual Studio 2008。
我有两个文件。
FileA.cpp
class ClassA : public baseClass
{
public:
A() throw();
~A() throw();
virtual int Init() throw();
virtual int Start() throw();
virtual int Stop() throw();
virtual void Cleanup() throw();
public:
int *pap;
HANDLE m_evTimerStop;
unsigned char m_ctrl;
CAtlList<int> m_list;
}
在FileA.cpp中,当我访问m_list时,一切都很好。
在FileB.cpp中,我声明了一个全局变量
extern ClassA g_pCA;
因此,如果某些函数可以访问m_list:
g_pCA-> m_list.RemoveAt(pos);
它崩溃了。如果我打电话给:
g_pCA-> m_list.GetCount();
在FileA中,计数将是正确的数字,例如10个元素。但是在FileB中,计数是一些随机的大数,有时是负数。您得到图片。
因此,我设法跟踪到以下事实:例如,文件A.cpp中的m_list位于地址0x9caba5,但在文件B.cpp中,m_list位于0x9caba8。有3个字节的差异,这使我怀疑内存对齐。
如果我将m_list移到m_ctrl上方,问题就消失了,并且文件中的地址匹配。
或者,如果我再次将m_ctrl从一个无符号字符更改为一个int,由于对齐,问题显然已经解决。
我不明白的是为什么不同文件中的编译器会应用不同的内存对齐规则。
是否有任何编译器标志来解决此问题?
谢谢。。。
最佳答案
假设我对#pragma pack
的猜测是正确的,解决方案是通过执行以下操作“仅打包实际需要它的结构”:
#pragma pack(push)
#pragma pack(1)
struct something_that_needs_to_be_packed
{
....
};
#pragma pack(pop)
现在,需要打包的数据将保持不变,但其他数据结构将不受影响。这是您想要的方式,因为打包和拥有未对齐的数据是一个坏主意,原因有几个,包括性能,在多线程系统中可靠地使用数据的能力等。