如何创造并尝试处理一个segmentation fault (core dumped)

segmentation fault (core dumped)是一个曾经让我非常头疼的报错,当然它还有一种中文形式,**段错误(核心已转移)**。

这种错误可能会在各种程序中出现,每次我都用软件名加报错信息去搜索,对于一些常见软件,我能够找到一些解决方案,于是我能按照它们提供的方式进行解决。而对于一些比较小众的软件,就几乎无解了。

直到我学习「c和指针」,我自己创造出了一个段错误,我终于不再害怕这个报错(当然也仅限于不在害怕而已)。

下面这行代码,我觉得和printf("hello world!\n")一样重要。”hello world!”让你开始入门编程,而理解下面的代码则让你深入编程。

1
2
3
4
5
6
7
#include <stdio.h>
int
main()
{
int *a ;
*a = 12;
}

我们可以将其复制到到一个error.c中,然后编译运行

1
2
3
gcc -o error error.c
./error
[2] 110633 segmentation fault (core dumped) ./error

在代码中,我们创建一个叫做a的指针变量,后面赋值语句则是把12存储在a所指向的内存地址,从逻辑上看好像没啥问题。其背后的问题,且听我慢慢道来。

a是一个指针变量,它和普通变量一样,它也有特定的内存地址,在那个内存递上也存放着值,该值是一个地址。对于一个普通变量而言,如果它们在声明的时候没有初始化,那么它们会有一个默认值,比如说int i;在我的机器上的结果是0。那么对于一个指针变量而言,如果没有在声明的时候没有初始化,它的值是什么呢?我用下面的代码测试了下

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

int
main(){
int i;
int *a;

printf("i:%d\n",i);
printf("a:%p\n",a);
}

在三次运行过程中,i的值始终为0,而a的值则是0x7ffee20e7dc0, 0x7ffc1d202d10,0x7fff50972560.这些都对应着内存上的一个地址。对*a进行赋值的过程,也就是对它对应的内存地址进行赋值,这就带来了一个问题。如果这些内存是合法能被我们操作的,那么这个操作将会顺利进行,不会出现报错,但是可能会出现一些你完全想象不到的问题。但如果内存是受到保护或者对应地址不存在(大部分情况),那么在Linux系统上就会跳出错误。

现在我们知道了,段错误(core dumped)是程序访问/使用它不能使用的内存地址所导致的,那么今后面对程序出现这个报错时,我们应该做呢?

  1. 使用软件名 + 段错误对应的英文(core dumped)进行检索, 比如说 “STAR core dumped”, 相对而言,用英文检索的资料会比较
  2. 检查自己的服务器内存是否充足,对于一些比对软件或者组装软件而言,它们比较占用内存,因此内存不够就会出现错误
  3. 检查自己的输入是否合法,这可能是程序没有合理的错误捕捉机制,导致遇到错误格式的输入依旧运行了代码,结果中间指针没有正确初始化,最终出错
  4. 更新软件:新的软件可能会修复之前代码错误
  5. 换个软件:有些软件的版本可能就停留在它发表文章那一天,那么这个工具可能也不太可