0

在重新编写一些现有代码以更好地简化它时,我在测试期间遇到了崩溃,我将其缩小到内存对齐问题,但我不确定如何在不掩盖问题的情况下修复它。是否有我可能需要的编译器原语。

我正在使用 Microsoft Visual Studio 2008。

我有两个文件。

文件A.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 从 unsigned char 更改为 int,则问题显然由于对齐而得到解决。

我不明白的是为什么不同文件中的编译器应用不同的内存对齐规则。

任何编译器标志来解决这个问题?

谢谢....阿姆罗

4

1 回答 1

2

假设我的猜测#pragma pack是正确的,解决方案是通过执行以下操作“仅打包实际需要它的结构”:

#pragma pack(push)
#pragma pack(1)
struct something_that_needs_to_be_packed
{
   .... 
};
#pragma pack(pop)

现在您需要打包的数据将如此,但其他数据结构不会受到影响。这就是您想要的方式,因为打包和拥有未对齐的数据是一个坏主意,原因有几个,包括性能、在多线程系统中可靠使用数据的能力等。

于 2013-06-21T21:50:11.613 回答