在调试问题时,出现了以下问题。(请忽略小代码错误;代码仅用于说明。)
定义了以下结构:
typedef struct box_t {
uint32_t x;
uint16_t y;
} box_t;
这个结构的实例是按值从一个函数传递到另一个函数(显然是简化的):
void fun_a(box_t b)
{
... use b ...
}
void fun_b(box_t bb)
{
// pass bb by value
int err = funa(bb);
}
void fun_c(void)
{
box_t real_b;
box_t some_b[10];
...
... use real_b and some_b[] ...
...
funb(real_b);
funb(some_b[3]);
...
box_t copy_b = some_b[5];
...
}
在某些情况下,box_t 的两个实例是这样比较的:
memcmp(bm, bn, sizeof(box_t));
在几个嵌套调用中,box_t arg 的字节使用如下方式转储:
char *p = (char*) &a_box_t_arg;
for (i=0; i < sizeof(box_t); i++) {
printf(" %02X", *p & 0xFF);
p++;
}
printf("\n");
sizeof(box_t) 为 8;有 2 个填充字节(发现在 uint16_t 之后)。转储显示结构的字段相等,但填充字节不相等;这导致 memcmp 失败(不足为奇)。
有趣的部分是发现“损坏的”焊盘值来自何处。往回追踪后发现,一些 box_t 实例被声明为局部变量,并像这样初始化:
box_t b;
b.x = 1;
b.y = 2;
上面没有(似乎)初始化填充字节,填充字节似乎包含“垃圾”(无论在为 b 分配的堆栈空间中是什么)。在大多数情况下,初始化是使用memset(b, 0, sizeof(box_t))
.
问题是通过 (1) 结构赋值或 (2) 通过值传递来初始化 box_t 的实例是否总是等同于 sizeof(box_t) 的 memcpy。是否只复制了“真实字段”的 6 个字节(而不是填充字节)。
从调试看来,memcpy sizeof(box_t) 等效项总是完成。是否有任何东西(例如,在标准中)实际指定了这一点?随着调试的进行,了解在处理填充字节方面可以依靠什么会很有帮助。
谢谢!(在 Ubuntu LTS 10.4 64 位上使用 GCC 4.4.3)
对于奖励积分:
void f(void)
{
box_t ba;
box_t bb;
box_t bc;
这 3 个实例被分配了 16 个字节,而 sizeof() 显示为 8。为什么会有额外的空间?