C/C++程序崩溃原因分析
概述
我们运行程序时经常会遇到异常崩溃,也就是我们常说的crash,下面我想总结一下crash出现的原因。而导致crash的主要原因就是段错误(Segmentation Fault)是不是很熟悉,相信每个运行过C程序的小伙伴都见过这两个单词,而且这种错误一般不给其他提示,看着很纠结。导致段错误的原因一般有
1.尝试访问我们系统中不存在的内存位置
2.试图在只读存储位置上进行写操作。
第一种原因就是字面意思,我想也不用解释了吧,比较常见一种情况是对空指针的读取操作。我们来看下第二种,举个小例子:
int main() { char *str = "crash"; *(str+1) = n; return 0; }
执行上面的代码就是报错:Segmentation fault (core dumped) 在代码中我们定义了字符串常量str,然后我们试图在字符串中加入一个字母n。我们知道字符串在内存中是作为常量保存的,就类似于数字0.1.2…,假设把“crash”看做数字0,n看做1,上面的行为就类似于给数字本身赋值,0 = 1,我们知道这种赋值是非法的。
3.试图访问受保护的内存位置, 例如内核内存
4.内存耗尽
4.1 堆栈溢出:发生不终止的内存位置递归的情况。
#include<stdio.h> void fun(int x) { if (x == 1) return; x = 6; fun(x); } int main() { int x = 5; fun(x); }
4.2 内存泄漏: 如果我们通过某个程序动态申请一些内存,但是用完后没有及时释放。当下次我们再调用这个程序时又会申请一次内存(请注意因为上一次申请的内存没有释放,所以我们以为只是使用第二次申请的内存,但是系统会认为两次申请的内存我们都在使用,因此第一次申请的内存还是处于被占用状态)多次调用程序之后,内存就会被耗尽,就会出现动态申请内存失败,程序就会crash。
int main() { for (int i=0; i<10000000; i++) { int *ptr = (int *)malloc(sizeof(int)); } }
5.缓冲区溢出
相信越界这个词大家都听过,其中最为常见的就是数组越界。
#include <stdio.h> int main() { char A[4] = ""; strcpy(A, "crash"); return 0; }
6.除以零
整数除以零默认的处理方式是终止进程 有点数学常识的都知道整数除以0是不允许的,在计算机中也是,这种情况其实出现的很少,但一旦出现,又很难被发现,所以 在做整数除法时,要判断被除数是否为0的情况。