核心转储文件大小发生奇怪变化

问题描述 投票:0回答:1

我有以下 C 代码片段,它们显然都会导致堆栈溢出错误:

a.c

int f(int i) {
    f(i);
}

int main() {
    f(1);
}

b.c

int f(int i) {
    f(i+1); 
}

int main() {
    f(1);
}

运行两者并查看

coredumpsctl list
中生成的结果后,输出大小非常不同:

Tue 2024-02-20 15:38:28 +0330 420696 1000 1000 SIGSEGV present  /tmp/a  204.2K
Tue 2024-02-20 15:38:30 +0330 420710 1000 1000 SIGSEGV present  /tmp/b  899.7K

第二个程序的 (

b.c
) 核心转储大小是第一个程序的 4 倍以上。这对我来说很奇怪,因为两个程序没有任何明显的差异。有人可以解释这种行为吗?

编辑

我使用此命令来编译这两个文件:

$ gcc a.c -o a && gcc b.c -o b

我使用的

gcc
版本:

$ gcc --version
gcc (Debian 12.2.0-14) 12.2.0

还为

a.c
生成了程序集(使用
objdump -S
):

0000000000001129 <f>:
    1129:   55                      push   %rbp
    112a:   48 89 e5                mov    %rsp,%rbp
    112d:   48 83 ec 10             sub    $0x10,%rsp
    1131:   89 7d fc                mov    %edi,-0x4(%rbp)
    1134:   8b 45 fc                mov    -0x4(%rbp),%eax
    1137:   89 c7                   mov    %eax,%edi
    1139:   e8 eb ff ff ff          call   1129 <f>
    113e:   90                      nop
    113f:   c9                      leave
    1140:   c3                      ret

0000000000001141 <main>:
    1141:   55                      push   %rbp
    1142:   48 89 e5                mov    %rsp,%rbp
    1145:   bf 01 00 00 00          mov    $0x1,%edi
    114a:   e8 da ff ff ff          call   1129 <f>
    114f:   b8 00 00 00 00          mov    $0x0,%eax
    1154:   5d                      pop    %rbp
    1155:   c3                      ret

对于

b.c

0000000000001129 <f>:
    1129:   55                      push   %rbp
    112a:   48 89 e5                mov    %rsp,%rbp
    112d:   48 83 ec 10             sub    $0x10,%rsp
    1131:   89 7d fc                mov    %edi,-0x4(%rbp)
    1134:   8b 45 fc                mov    -0x4(%rbp),%eax
    1137:   83 c0 01                add    $0x1,%eax
    113a:   89 c7                   mov    %eax,%edi
    113c:   e8 e8 ff ff ff          call   1129 <f>
    1141:   90                      nop
    1142:   c9                      leave
    1143:   c3                      ret

0000000000001144 <main>:
    1144:   55                      push   %rbp
    1145:   48 89 e5                mov    %rsp,%rbp
    1148:   bf 01 00 00 00          mov    $0x1,%edi
    114d:   e8 d7 ff ff ff          call   1129 <f>
    1152:   b8 00 00 00 00          mov    $0x0,%eax
    1157:   5d                      pop    %rbp
    1158:   c3                      ret
c stack-overflow coredump
1个回答
0
投票

核心转储大小的差异是由于编译器优化造成的。该问题是由于编译器优化两个程序中的递归函数调用的方式不同造成的。由于您的代码都表现出无限递归,这最终将导致堆栈溢出错误。

a.c
中,每个递归调用都与前一个相同,从而导致
tail-recursive
模式,并且许多编译器能够通过将
tail-recursive
函数转换为迭代循环来优化它们,这会导致更有效的堆栈使用和较小的核心转储大小。

而在

b.c
中,
i
在进行递归调用之前被修改,这会阻止编译器将递归优化为
tail-recursive
模式,最终导致更大的堆栈使用和更大的核心转储大小。

© www.soinside.com 2019 - 2024. All rights reserved.