编译器的怪异行为-调试器

时间:2019-06-21 09:25:30

标签: c gcc gdb

这个问题与我在此分享的上一个问题密切相关。但是...

我有一个相当大的项目,正在对其进行单元测试和集成测试。不幸的是,除了细小的片段之外,我无法共享代码,而无论如何,这都是要共享的大型项目。

我会尽力总结一下... 类型定义如下:

typedef struct { 
s32 s32IntLimitHigh; 
s32 s32IntLimitLow; 
s32 s32RegLimitHigh; 
s32 s32RegLimitLow; 
u16 u16IntGain; 
u16 u16PropGain; 
u16 u16IntStep; 
BOOL BOOLFreeze; 
} structPIreg;

单个成员的类型通过其名称非常清楚。
定义了两个数组,如下所示:

structPIreg expected_VectParPI[VECT_PI_LENGTH];
structPIreg VectParPI[VECT_PI_LENGTH];

因为它用于单元测试,所以我具有原始变量及其期望值。 数组由8个元素组成。

sizeof (VectParPI[1]) is 29 :

4 * s32 + 3 * u16 + BOOL = 4 * 4 + 3 * 4 + 1 = 29
u16在原始计算机上是16位,在x86架构上是32位。

我编译,测试运行,并且得到奇怪的结果。 因此,我开始进行调试会话,这里的事情变得更加奇怪。

现在,问题在于两个变量的结构大小似乎不同。 而且我在调试器上看到的是一致的。

我将张贴两张变量监视窗口的图片,以使您理解。 在此监视窗口中,我计算两个数组的第二个和第一个元素之间的字节偏移量。

(char*)&VectParPI[1]-(char*)&VectParPI[0]   long    32  
(char*)&expected_VectParPI[1]-(char*)&expected_VectParPI[0] long    29  

watch windows

如您所见,偏移量是不同的。 但是我不知道为什么。 在目标文件中,相同类型的两个不同变量的偏移量/大小如何不同?

更有意思的是,当我启动调试器并且gdb在main上暂停时,这两个大小是正确的(每个29个)。 比我在某处设置断点,并且在达到断点时,我看到的大小分别为32和29。

如何更改内存地址? 就像结构在内存中转移一样。 我只是不知道为什么。。。

作为我梦dream以求的“证明”,我附加了与以前相同的观察窗口。 您会看到eclipse / gdb以黄色突出显示了大小和偏移量,因为在某些时候它们已从29变为32。 真有趣....:)

highlighted watch window

1 个答案:

答案 0 :(得分:0)

  

4 * s32 + 3 * u16 + BOOL = 4 * 4 + 3 * 4 + 1 = 29

这不是此结构预期的sizeof 。由于填充原因,预期的sizeof为32。

获得29的原因是该结构具有__attribute__((packed)),而获得两个不同大小的事实意味着您的某些编译单元具有packed属性,其他人没有。

这违反了一个定义规则和未定义的行为。

您需要找到此packed的来源,并使它在整个程序中保持一致。