gcc的-fstack-usage选项对叶函数的栈使用统计是否有误?
gcc
-fstack-usage对叶函数栈使用统计的异常 对比gcc的-fstack-usage选项给出的两个相似函数(一个含函数调用,一个不含)的栈使用情况时,得到了不同结果。
初始测试代码
void donothing(void) {} void leaf(void) { int i = 0; } void noleaf(void) { int i = 0; donothing(); } int main(void) { leaf(); noleaf(); return 0; }
直观来看,leaf和noleaf函数局部变量相同,栈大小应一致,但-fstack-usage输出结果不同:
$ gcc -fstack-usage -o exe leaf.c $ cat leaf.su leaf.c:1:6:donothing 16 static leaf.c:3:6:leaf 16 static leaf.c:7:6:noleaf 32 static leaf.c:12:5:main 16 static
可见leaf函数栈大小与donothing相同,局部变量未被统计。
查看汇编代码发现,leaf和noleaf对栈的操作方式不同:
000000000000112c <leaf>: 112c: 55 push %rbp 112d: 48 89 e5 mov %rsp,%rbp 1130: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) 1137: 90 nop 1138: 5d pop %rbp 1139: c3 retq 000000000000113a <noleaf>: 113a: 55 push %rbp 113b: 48 89 e5 mov %rsp,%rbp 113e: 48 83 ec 10 sub $0x10,%rsp 1142: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) 1149: e8 d7 ff ff ff callq 1125 <donothing> 114e: 90 nop 114f: c9 leaveq 1150: c3 retq
noleaf通过sub $0x10,%rsp分配栈空间,leaf则直接用movl $0x0,-0x4(%rbp)存储局部变量,无预分配。但leaf的局部变量仍在栈上,为何栈使用量未统计它?
补充测试(排除callq和对齐影响)
有观点认为差异由callq和对齐要求导致,故修改代码:
void donothing(void) {} void leaf(void) { { int i = 0; int j = 0; int k = 0; int l = 0; } { int i = 0; int j = 0; int k = 0; int l = 0; } { int i = 0; int j = 0; int k = 0; int l = 0; } { int i = 0; int j = 0; int k = 0; int l = 0; } } void noleaf(void) { { int i = 0; int j = 0; int k = 0; int l = 0; } { int i = 0; int j = 0; int k = 0; int l = 0; } { int i = 0; int j = 0; int k = 0; int l = 0; } { int i = 0; int j = 0; int k = 0; int l = 0; } donothing(); } int main(void) { leaf(); noleaf(); return 0; }
若差异仅由callq和对齐导致,两函数差异不应超16字节,但-fstack-usage结果如下:
su.c:1:6:donothing 16 static su.c:3:6:leaf 16 static su.c:10:6:noleaf 80 static su.c:18:5:main 16 static
noleaf用80字节符合预期(64字节存局部变量,16字节存栈指针等),但leaf栈大小仍为16字节,局部变量未被统计。
对应的汇编代码如下:
000000000000112c <leaf>: 112c: 55 push %rbp 112d: 48 89 e5 mov %rsp,%rbp 1130: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) 1137: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp) 113e: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%rbp) 1145: c7 45 f0 00 00 00 00 movl $0x0,-0x10(%rbp) 114c: c7 45 ec 00 00 00 00 movl $0x0,-0x14(%rbp) 1153: c7 45 e8 00 00 00 00 movl $0x0,-0x18(%rbp) 115a: c7 45 e4 00 00 00 00 movl $0x0,-0x1c(%rbp) 1161: c7 45 e0 00 00 00 00 movl $0x0,-0x20(%rbp) 1168: c7 45 dc 00 00 00 00 movl $0x0,-0x24(%rbp) 116f: c7 45 d8 00 00 00 00 movl $0x0,-0x28(%rbp) 1176: c7 45 d4 00 00 00 00 movl $0x0,-0x2c(%rbp) 117d: c7 45 d0 00 00 00 00 movl $0x0,-0x30(%rbp) 1184: c7 45 cc 00 00 00 00 movl $0x0,-0x34(%rbp) 118b: c7 45 c8 00 00 00 00 movl $0x0,-0x38(%rbp) 1192: c7 45 c4 00 00 00 00 movl $0x0,-0x3c(%rbp) 1199: c7 45 c0 00 00 00 00 movl $0x0,-0x40(%rbp) 11a0: 90 nop 11a1: 5d pop %rbp 11a2: c3 retq 00000000000011a3 <noleaf>: 11a3: 55 push %rbp 11a4: 48 89 e5 mov %rsp,%rbp 11a7: 48 83 ec 40 sub $0x40,%rsp 11ab: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) 11b2: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp) 11b9: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%rbp) 11c0: c7 45 f0 00 00 00 00 movl $0x0,-0x10(%rbp) 11c7: c7 45 ec 00 00 00 00 movl $0x0,-0x14(%rbp) 11ce: c7 45 e8 00 00 00 00 movl $0x0,-0x18(%rbp) 11d5: c7 45 e4 00 00 00 00 movl $0x0,-0x1c(%rbp) 11dc: c7 45 e0 00 00 00 00 movl $0x0,-0x20(%rbp) 11e3: c7 45 dc 00 00 00 00 movl $0x0,-0x24(%rbp) 11ea: c7 45 d8 00 00 00 00 movl $0x0,-0x28(%rbp) 11f1: c7 45 d4 00 00 00 00 movl $0x0,-0x2c(%rbp) 11f8: c7 45 d0 00 00 00 00 movl $0x0,-0x30(%rbp) 11ff: c7 45 cc 00 00 00 00 movl $0x0,-0x34(%rbp) 1206: c7 45 c8 00 00 00 00 movl $0x0,-0x38(%rbp) 120d: c7 45 c4 00 00 00 00 movl $0x0,-0x3c(%rbp) 1214: c7 45 c0 00 00 00 00 movl $0x0,-0x40(%rbp) 121b: e8 05 ff ff ff callq 1125 <donothing> 1220: 90 nop 1221: c9 leaveq 1222: c3 retq
因此,仅用callq语句无法解释两函数的栈使用差异,怀疑-fstack-usage对叶函数的统计有误。
内容的提问来源于stack exchange,提问作者Pierre
相关产品推荐
相关产品推荐

