您的位置:首页 > 理论基础 > 数据结构算法

《coredump问题原理探究》Linux x86版5.9节C风格数据结构内存布局之联合体

2014-11-22 17:00 495 查看
在C语言中,联合体(union)有点像结构体那样,把不同类型的数据组织起来,但和结构体不大一样,在结构体各成员有各自的内存空间,一个结构体对象的总长度是各成员长度之和。而在联合体中,各成员共享一段内存空间,一个联合体对象的长度等于各成员中最长的长度。

由上面描述可知,联合体应该具备多面性,即在汇编层面上,有时候会显示结构体的特征,或数组特征,或其它基本数据类型特征。

先看一下例子:

1	 #include <stdio.h>
2	 union xuzhina_dump_c05_s4
3	 {
4	     int i;
5	     char hello[4];
6	 };
7
8	 int main()
9	 {
10	     union xuzhina_dump_c05_s4 test;
11	     test.i = 0x656463;
12	     for ( int i = 0; i < 4; i++ )
13	     {
14	         printf( "%c", test.hello[i] );
15	     }
16
17	     printf( "\n" );
18	     return 0;
19	 }


汇编代码:

(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    $0x20,%esp
0x08048579 <+9>:     movl   $0x656463,0x18(%esp)
0x08048581 <+17>:    movl   $0x0,0x1c(%esp)
0x08048589 <+25>:    jmp    0x80485a8 <main+56>
0x0804858b <+27>:    lea    0x18(%esp),%edx
0x0804858f <+31>:    mov    0x1c(%esp),%eax
0x08048593 <+35>:    add    %edx,%eax
0x08048595 <+37>:    movzbl (%eax),%eax
0x08048598 <+40>:    movsbl %al,%eax
0x0804859b <+43>:    mov    %eax,(%esp)
0x0804859e <+46>:    call   0x8048430 <putchar@plt>
0x080485a3 <+51>:    addl   $0x1,0x1c(%esp)
0x080485a8 <+56>:    cmpl   $0x3,0x1c(%esp)
0x080485ad <+61>:    setle  %al
0x080485b0 <+64>:    test   %al,%al
0x080485b2 <+66>:    jne    0x804858b <main+27>
0x080485b4 <+68>:    movl   $0xa,(%esp)
0x080485bb <+75>:    call   0x8048430 <putchar@plt>
0x080485c0 <+80>:    mov    $0x0,%eax
0x080485c5 <+85>:    jmp    0x80485cf <main+95>
0x080485c7 <+87>:    mov    %eax,(%esp)
0x080485ca <+90>:    call   0x8048460 <_Unwind_Resume@plt>
0x080485cf <+95>:    leave
0x080485d0 <+96>:    ret
End of assembler dump.


从上面汇编代码来看,unionxuzhina_dump_c05_s4确实以int和char数组进行访问。见下面这两组指令

0x08048579 <+9>:     movl   $0x656463,0x18(%esp)

0x0804858b <+27>:    lea    0x18(%esp),%edx
0x0804858f <+31>:    mov    0x1c(%esp),%eax
0x08048593 <+35>:    add    %edx,%eax
0x08048595 <+37>:    movzbl (%eax),%eax


由上面的探讨,union成员类型最好避免是指针类型。因为指针容易被覆盖,会发生“Accessviolation”的错误。假设指针是函数指针,则会出现上一节的coredump。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐