读书人

《coredump有关问题原理探究》Linux x

发布时间: 2013-04-02 12:35:26 作者: rapoo

《coredump问题原理探究》Linux x86版5.5节C风格数据结构内存布局之基本数据类型构成的结构体

在C语言里,结构体是不同类型数据结构的集合。由于结构体比较复杂,分为几种情况来讨论:

1. 成员全是由基本数据类型构成

2. 成员有基本数据类型,也有其它结构体构成,构成成员的结构体是1,2两种情况。

3. 结构体构成的数组


这一节先讨论第一种情况.要了解这种类型结构体的内存布局,首先要知道成员在内存里是如何排序,及各个成员在内存占的大小。先看一个例子

(gdb) disassemble equal                                                       Dump of assembler code for function _Z5equalP24xuzhina_dump_c05_s3_struS0_:   0x08048470 <+0>:     push   %ebp   0x08048471 <+1>:     mov    %esp,%ebp   0x08048473 <+3>:     mov    0x8(%ebp),%eax   0x08048476 <+6>:     movzbl (%eax),%edx   0x08048479 <+9>:     mov    0xc(%ebp),%eax   0x0804847c <+12>:    movzbl (%eax),%eax   0x0804847f <+15>:    cmp    %al,%dl   0x08048481 <+17>:    je     0x804848a <_Z5equalP24xuzhina_dump_c05_s3_struS0_+26>   0x08048483 <+19>:    mov    $0x0,%eax   0x08048488 <+24>:    jmp    0x80484c0 <_Z5equalP24xuzhina_dump_c05_s3_struS0_+80>   0x0804848a <+26>:    mov    0x8(%ebp),%eax   0x0804848d <+29>:    movzwl 0x2(%eax),%edx   0x08048491 <+33>:    mov    0xc(%ebp),%eax   0x08048494 <+36>:    movzwl 0x2(%eax),%eax   0x08048498 <+40>:    cmp    %ax,%dx   0x0804849b <+43>:    je     0x80484a4 <_Z5equalP24xuzhina_dump_c05_s3_struS0_+52>   0x0804849d <+45>:    mov    $0x0,%eax   0x080484a2 <+50>:    jmp    0x80484c0 <_Z5equalP24xuzhina_dump_c05_s3_struS0_+80>   0x080484a4 <+52>:    mov    0x8(%ebp),%eax   0x080484a7 <+55>:    mov    0x4(%eax),%edx   0x080484aa <+58>:    mov    0xc(%ebp),%eax   0x080484ad <+61>:    mov    0x4(%eax),%eax   0x080484b0 <+64>:    cmp    %eax,%edx   0x080484b2 <+66>:    je     0x80484bb <_Z5equalP24xuzhina_dump_c05_s3_struS0_+75>   0x080484b4 <+68>:    mov    $0x0,%eax   0x080484b9 <+73>:    jmp    0x80484c0 <_Z5equalP24xuzhina_dump_c05_s3_struS0_+80>   0x080484bb <+75>:    mov    $0x1,%eax   0x080484c0 <+80>:    pop    %ebp   0x080484c1 <+81>:    ret    End of assembler dump.(gdb) disassemble mainDump of assembler code for function main:   0x080484c2 <+0>:     push   %ebp   0x080484c3 <+1>:     mov    %esp,%ebp   0x080484c5 <+3>:     sub    $0x18,%esp   0x080484c8 <+6>:     movb   $0x61,-0x8(%ebp)   0x080484cc <+10>:    movw   $0xa,-0x6(%ebp)   0x080484d2 <+16>:    movl   $0x14,-0x4(%ebp)   0x080484d9 <+23>:    movb   $0x61,-0x10(%ebp)   0x080484dd <+27>:    movw   $0xa,-0xe(%ebp)   0x080484e3 <+33>:    movl   $0x15,-0xc(%ebp)   0x080484ea <+40>:    lea    -0x10(%ebp),%eax   0x080484ed <+43>:    mov    %eax,0x4(%esp)   0x080484f1 <+47>:    lea    -0x8(%ebp),%eax   0x080484f4 <+50>:    mov    %eax,(%esp)   0x080484f7 <+53>:    call   0x8048470 <_Z5equalP24xuzhina_dump_c05_s3_struS0_>   0x080484fc <+58>:    test   %al,%al   0x080484fe <+60>:    je     0x8048507 <main+69>   0x08048500 <+62>:    mov    $0x0,%eax   0x08048505 <+67>:    jmp    0x804850c <main+74>   0x08048507 <+69>:    mov    $0x1,%eax   0x0804850c <+74>:    leave     0x0804850d <+75>:    ret    End of assembler dump.

从equal函数的汇编代码可以看到,

1. 结构体都是一个基地址,从它三个成员的寻址看到,都是先把基地址放到某寄存器里。如mov 0x8(%ebp),%eax

2. 结构体成员的访问,都在基址基础上加上前面所有成员的大小。如成员c,前面a和b占四个字节,所以就有“mov 0x8(%ebp),%eax”, “mov 0x4(%eax),%edx”.

3. 每个成员与基址的偏移量,不是构成一个等差数列。



读书人网 >UNIXLINUX

热点推荐