69 局部变量的空间分配
前言
这是一个 老生常谈的问题
这里主要是探索在 函数中分配的局部变量 他使用的空间是哪里的空间, 有什么特征
然后 我们来看一下 这里的编译之后的是一个实现
测试用例
和 指针的减法操作 的测试用例一样
只是我们这里 更加关注与 list 和 p1 和 p2
#include<stdio.h>typedef struct Person {int age;int height;
// int field03;
} Person;int main(int argc, char **argv) {struct Person list[10], *p1, *p2;list[0].age = 12;list[2].age = 22;p1 = &list[0];p2 = &list[2];int delta = (int) (p2 - p1);printf(" the delta : %d \n", delta);return 0;}
查看 list, p1, p2
运行时上下文如下
(gdb) b Test17PointerDelta.c:20
Breakpoint 1 at 0x4005df: file Test17PointerDelta.c, line 20.
(gdb) run
Starting program: /root/Desktop/linux/HelloWorld/Test17PointerDeltaBreakpoint 1, main (argc=1, argv=0x7fffffffe578) at Test17PointerDelta.c:20
20 int delta = (int) (p2 - p1);
(gdb) disassemble
Dump of assembler code for function main:0x0000000000400596 <+0>: push %rbp0x0000000000400597 <+1>: mov %rsp,%rbp0x000000000040059a <+4>: sub $0x90,%rsp0x00000000004005a1 <+11>: mov %edi,-0x84(%rbp)0x00000000004005a7 <+17>: mov %rsi,-0x90(%rbp)0x00000000004005ae <+24>: mov %fs:0x28,%rax0x00000000004005b7 <+33>: mov %rax,-0x8(%rbp)0x00000000004005bb <+37>: xor %eax,%eax0x00000000004005bd <+39>: movl $0xc,-0x60(%rbp)0x00000000004005c4 <+46>: movl $0x16,-0x50(%rbp)0x00000000004005cb <+53>: lea -0x60(%rbp),%rax0x00000000004005cf <+57>: mov %rax,-0x70(%rbp)0x00000000004005d3 <+61>: lea -0x60(%rbp),%rax0x00000000004005d7 <+65>: add $0x10,%rax0x00000000004005db <+69>: mov %rax,-0x68(%rbp)
=> 0x00000000004005df <+73>: mov -0x68(%rbp),%rdx0x00000000004005e3 <+77>: mov -0x70(%rbp),%rax0x00000000004005e7 <+81>: sub %rax,%rdx0x00000000004005ea <+84>: mov %rdx,%rax0x00000000004005ed <+87>: sar $0x3,%rax0x00000000004005f1 <+91>: mov %eax,-0x74(%rbp)0x00000000004005f4 <+94>: mov -0x74(%rbp),%eax0x00000000004005f7 <+97>: mov %eax,%esi0x00000000004005f9 <+99>: mov $0x4006b4,%edi0x00000000004005fe <+104>: mov $0x0,%eax0x0000000000400603 <+109>: call 0x400470 <printf@plt>0x0000000000400608 <+114>: mov $0x0,%eax0x000000000040060d <+119>: mov -0x8(%rbp),%rcx0x0000000000400611 <+123>: xor %fs:0x28,%rcx0x000000000040061a <+132>: je 0x400621 <main+139>0x000000000040061c <+134>: call 0x400460 <__stack_chk_fail@plt>0x0000000000400621 <+139>: leave0x0000000000400622 <+140>: ret
End of assembler dump.
(gdb) info registers
rax 0x7fffffffe440 140737488348224
rbx 0x0 0
rcx 0x0 0
rdx 0x7fffffffe588 140737488348552
rsi 0x7fffffffe578 140737488348536
rdi 0x1 1
rbp 0x7fffffffe490 0x7fffffffe490
rsp 0x7fffffffe400 0x7fffffffe400
r8 0x4006a0 4196000
r9 0x7ffff7de7af0 140737351940848
r10 0x846 2118
r11 0x7ffff7a2d750 140737348032336
r12 0x4004a0 4195488
r13 0x7fffffffe570 140737488348528
r14 0x0 0
r15 0x0 0
rip 0x4005df 0x4005df <main+73>
eflags 0x202 [ IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb) print &list
$1 = (struct Person (*)[10]) 0x7fffffffe430
(gdb) print &p1
$2 = (struct Person **) 0x7fffffffe420
(gdb) print &p2
$3 = (struct Person **) 0x7fffffffe428
(gdb) print &list[9]
$4 = (struct Person *) 0x7fffffffe478
(gdb) print &list[0]
$5 = (struct Person *) 0x7fffffffe430(gdb) x /10gx 0x7fffffffe430
0x7fffffffe430: 0x000000000000000c 0x0000000000000000
0x7fffffffe440: 0x0000000000000016 0x0000000000000000
0x7fffffffe450: 0x0000000000000001 0x000000000040067d
0x7fffffffe460: 0x0000000000000000 0x0000000000000000
0x7fffffffe470: 0x0000000000400630 0x00000000004004a0
结合这张图可以更加明晰的看到 list, p1, p2 的相关地址偏移信息
可以看到的是 局部变量的空间分配时分配在 当前栈帧的局部变量表预留的空间中的
局部变量的 sizeof
测试用例中增加一个 sizeof 的计算, 然后 查看反汇编之后的 sizeof 为编译计算好的常量 0x50
测试用例如下
#include<stdio.h>typedef struct Person {int age;int height;
// int field03;
} Person;int main(int argc, char **argv) {struct Person list[10], *p1, *p2;list[0].age = 12;list[2].age = 22;p1 = &list[0];p2 = &list[2];int delta = (int) (p2 - p1);printf(" the delta : %d \n", delta);printf(" test %d", sizeof(list));return 0;}
编译之后的代码如下
(gdb) disassemble
Dump of assembler code for function main:0x0000000000400596 <+0>: push %rbp0x0000000000400597 <+1>: mov %rsp,%rbp0x000000000040059a <+4>: sub $0x90,%rsp0x00000000004005a1 <+11>: mov %edi,-0x84(%rbp)0x00000000004005a7 <+17>: mov %rsi,-0x90(%rbp)0x00000000004005ae <+24>: mov %fs:0x28,%rax0x00000000004005b7 <+33>: mov %rax,-0x8(%rbp)0x00000000004005bb <+37>: xor %eax,%eax0x00000000004005bd <+39>: movl $0xc,-0x60(%rbp)0x00000000004005c4 <+46>: movl $0x16,-0x50(%rbp)0x00000000004005cb <+53>: lea -0x60(%rbp),%rax0x00000000004005cf <+57>: mov %rax,-0x70(%rbp)0x00000000004005d3 <+61>: lea -0x60(%rbp),%rax0x00000000004005d7 <+65>: add $0x10,%rax0x00000000004005db <+69>: mov %rax,-0x68(%rbp)
=> 0x00000000004005df <+73>: mov -0x68(%rbp),%rdx0x00000000004005e3 <+77>: mov -0x70(%rbp),%rax0x00000000004005e7 <+81>: sub %rax,%rdx0x00000000004005ea <+84>: mov %rdx,%rax0x00000000004005ed <+87>: sar $0x3,%rax0x00000000004005f1 <+91>: mov %eax,-0x74(%rbp)0x00000000004005f4 <+94>: mov -0x74(%rbp),%eax0x00000000004005f7 <+97>: mov %eax,%esi0x00000000004005f9 <+99>: mov $0x4006c4,%edi0x00000000004005fe <+104>: mov $0x0,%eax0x0000000000400603 <+109>: call 0x400470 <printf@plt>0x0000000000400608 <+114>: mov $0x50,%esi0x000000000040060d <+119>: mov $0x4006d6,%edi0x0000000000400612 <+124>: mov $0x0,%eax0x0000000000400617 <+129>: call 0x400470 <printf@plt>0x000000000040061c <+134>: mov $0x0,%eax0x0000000000400621 <+139>: mov -0x8(%rbp),%rcx0x0000000000400625 <+143>: xor %fs:0x28,%rcx0x000000000040062e <+152>: je 0x400635 <main+159>0x0000000000400630 <+154>: call 0x400460 <__stack_chk_fail@plt>0x0000000000400635 <+159>: leave0x0000000000400636 <+160>: ret
完