版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1344508
由于结构体是不同类型数据结构的集合,那么一个结构体的成员可以是基本数据类型,也可以是另外一个结构体类型。那么复合类型的结构体又有什么特征呢。
先看一个例子:
#include <stdio.h>
struct xuzhina_dump_c05_s3_2_sub
{
char a;
short b;
};
struct xuzhina_dump_c05_s3_2
{
int c;
long d;
struct xuzhina_dump_c05_s3_2_sub sub;
};
int main()
{
struct xuzhina_dump_c05_s3_2 test;
scanf( "%c, %hd, %d, %ld", &test.sub.a, &test.sub.b,
&test.c, &test.d );
return test.c + test.d;
}
汇编
(gdb) disassemble main
Dump of assembler code for function main:
0x08048570 <+0>: push %ebp
0x08048571 <+1>: mov %esp,%ebp
0x08048573 <+3>: and $0xfffffff0,%esp
0x08048576 <+6>: sub $0x30,%esp
0x08048579 <+9>: lea 0x24(%esp),%eax
0x0804857d <+13>: add $0x4,%eax
0x08048580 <+16>: mov %eax,0x10(%esp)
0x08048584 <+20>: lea 0x24(%esp),%eax
0x08048588 <+24>: mov %eax,0xc(%esp)
0x0804858c <+28>: lea 0x24(%esp),%eax
0x08048590 <+32>: add $0xa,%eax
0x08048593 <+35>: mov %eax,0x8(%esp)
0x08048597 <+39>: lea 0x24(%esp),%eax
0x0804859b <+43>: add $0x8,%eax
0x0804859e <+46>: mov %eax,0x4(%esp)
0x080485a2 <+50>: movl $0x8048664,(%esp)
0x080485a9 <+57>: call 0x8048440 <scanf@plt>
0x080485ae <+62>: mov 0x24(%esp),%edx
0x080485b2 <+66>: mov 0x28(%esp),%eax
0x080485b6 <+70>: add %edx,%eax
0x080485b8 <+72>: jmp 0x80485c2 <main+82>
0x080485ba <+74>: mov %eax,(%esp)
0x080485bd <+77>: call 0x8048460 <_Unwind_Resume@plt>
0x080485c2 <+82>: leave
0x080485c3 <+83>: ret
End of assembler dump.
由
0x08048597 <+39>: lea 0x24(%esp),%eax
0x0804859b <+43>: add $0x8,%eax
0x0804859e <+46>: mov %eax,0x4(%esp)
对test.sub.a的访问,可知,它是直接把test的基地址esp+0x24加上8(c和d的大小总和为8)来访问。
同样对test.sub.b的访问:
0x0804858c <+28>: lea 0x24(%esp),%eax
0x08048590 <+32>: add $0xa,%eax
0x08048593 <+35>: mov %eax,0x8(%esp)
可知,它是直接把test的基地址esp+0x24加上10(0xa)(c和d的大小总和为8,而a是char由于对齐2个字节,所以偏移量为0xa)来访问。
也就是说,对test的成员变量sub的成员访问,完全可以无视sub的存在,不需要再设定sub的基地址。
由上可知,复合结构体和基本数据类型构成的结构体在特征上没什么区别。如果在coredump发现是结构体成员导致,可以通过结构体定义算偏移值来确定是哪个成员出了问题。