我有以下两个显然都会导致堆栈溢出错误的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

Also assembly generated for a.c个 (using 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

推荐答案

The default in systemd's coredump.conf is Compress=yes, according to the man page.
Presumably that's with zstd or gzip.

大小不仅取决于正在使用的地址空间量,还取决于数据的可压缩程度.你的a有一个重复的模式,在每个堆栈帧中都有相同的i,所以压缩会更好.(每次保存的RBP将不同,但返回地址是相同的,并且32字节帧的未写入12字节将在_start/动态链接器代码在到达Main之前可能已被玷污的前几帧下方为0.)

b不会:i+1在每个堆栈帧中生成一个不同的值,该值以不同的方式更改为保存的RBP.

我不认为zstd或gZip寻找的是变化模式的增量压缩,而是完全匹配.或者,如果他们确实在寻找增量,那么可能有两个不断变化的值(保存的RBP和溢出的i)就不会实现这一点.两者通常只在低位字节中更改,i更改1,SAVED-RBP更改32(每个堆栈帧的大小).

C++相关问答推荐

字符串令牌化xpath表达式

当main函数调用被重构时,C函数给出错误的结果

为静态库做准备中的奇怪行为

错误Cygwin_Except::Open_stackdupfile:正在转储堆栈跟踪是什么?

防止规范模式在C++中 echo 特殊字符

如何在GET_STRING输入后对少数几个特定字符串进行C判断?

指向不同类型的指针是否与公共初始序列规则匹配?

`预期说明符-限定符-列表在‘(三元运算符中的’token`‘之前

我可以创建适用于不同endian的 colored颜色 struct 吗?

如何对现有的双向循环链表进行排序?

从CentOS 7到Raspberry PI 2B的交叉编译-无法让LIBC和System Include标头一起工作

为什么会导致分段故障?(C语言中的一个程序,统计文件中某个单词的出现次数)

当我在34mb的.mp4文件中使用FREAD时,我得到了一个分段错误,我如何解决它?

如何在MSVC中使用intSafe.h函数?

';malloc():损坏的顶部大小';分配超过20万整数后

I';我试着从.txt文件中读取文本,并用c计算其中的单词数量

C struct 中的冒泡排序

为什么创建局部变量的指针需要过程在堆栈上分配空间?

C 中从 Unix 纪元时间转换的损坏

为什么这里的符号没有解析?