DWARF信息中DIE显示结构体字段内存重叠,原因何在?
为何DWARF信息显示结构体位字段与普通字段内存重叠?
测试代码
struct all_t { unsigned a:13; char b; }; struct all_t all; int main(int argc, char* argv[]) { all.b = 3; all.a = 0xf; printf("%d\n", all.a); printf("%d\n", all.b); printf("%u\n", sizeof(all)); return 0; }
编译命令
gcc -O0 -g test.c -o test.elf
成员'a'的DIE信息
DIE DW_TAG_member, size=13, has_children=False |DW_AT_name : AttributeValue(name='DW_AT_name', form='DW_FORM_string', value=b'a', raw_value=b'a', offset=134) |DW_AT_decl_file : AttributeValue(name='DW_AT_decl_file', form='DW_FORM_data1', value=1, raw_value=1, offset=136) |DW_AT_decl_line : AttributeValue(name='DW_AT_decl_line', form='DW_FORM_data1', value=43, raw_value=43, offset=137) |DW_AT_type : AttributeValue(name='DW_AT_type', form='DW_FORM_ref4', value=66, raw_value=66, offset=138) |DW_AT_byte_size : AttributeValue(name='DW_AT_byte_size', form='DW_FORM_data1', value=4, raw_value=4, offset=142) |DW_AT_bit_size : AttributeValue(name='DW_AT_bit_size', form='DW_FORM_data1', value=13, raw_value=13, offset=143) |DW_AT_bit_offset : AttributeValue(name='DW_AT_bit_offset', form='DW_FORM_data1', value=19, raw_value=19, offset=144) |DW_AT_data_member_location: AttributeValue(name='DW_AT_data_member_location', form='DW_FORM_data1', value=0, raw_value=0, offset=145)
成员'b'的DIE信息
DIE DW_TAG_member, size=10, has_children=False |DW_AT_name : AttributeValue(name='DW_AT_name', form='DW_FORM_string', value=b'b', raw_value=b'b', offset=147) |DW_AT_decl_file : AttributeValue(name='DW_AT_decl_file', form='DW_FORM_data1', value=1, raw_value=1, offset=149) |DW_AT_decl_line : AttributeValue(name='DW_AT_decl_line', form='DW_FORM_data1', value=44, raw_value=44, offset=150) |DW_AT_type : AttributeValue(name='DW_AT_type', form='DW_FORM_ref4', value=114, raw_value=114, offset=151) |DW_AT_data_member_location: AttributeValue(name='DW_AT_data_member_location', form='DW_FORM_data1', value=2, raw_value=2, offset=155)
重叠原因分析
从DWARF信息可明确:
- 位字段
a占据结构体偏移0字节开始的4字节空间,覆盖第19位到第31位(共13位) - 普通字段
b占据结构体偏移2字节处的1字节空间,覆盖第16位到第23位
两者在第19-23位存在重叠,这是编译器的实现定义行为,核心逻辑如下:
位字段的存储单元规则
位字段a的基础类型是unsigned,在32位系统中默认占4字节。编译器会为其分配完整的4字节存储单元,即使它仅使用13位。普通字段的对齐策略
char类型的对齐要求为1字节,无需强制对齐到4字节边界。编译器为节省内存,直接将b放入a所在的4字节存储单元的剩余空间(偏移2字节处),而非重新分配新的存储单元。重叠的必然性
a的位偏移19位对应4字节单元的第2字节第3位,而b占据第2字节的全部8位,自然会与a的前5位产生重叠。
实际运行影响
运行程序后会发现,两个字段的重叠区域会被互相覆盖:
- 先给
b赋值3(二进制00000011),再给a赋值0xf(二进制1111),a的低5位会覆盖b的后3位,最终b的值会变为0(具体结果取决于端序,但核心是重叠区域数据会被覆盖)。
内容的提问来源于stack exchange,提问作者so.very.tired
相关产品推荐
相关产品推荐

