有关野指针和段错误,其实在前面已经断断续续的提到过,
只是没有明确的称呼为“野指针”和“段错误”而已,这里需要再完整的讲述下


一、野指针

什么是野指针?

所谓野指针就是,指针(地址)是一个随机值,这个随机值会指向任何可能的空间,这就是野指针

野指针的危害?

野指针可能会导致两种情况,这两种情况其实在前面描述过。

  • (1)指针没有对应任何真实的存储空间
  • (2)指向其它空间:
    1)其它空间不允许操作
    2)允许操作
    这种最麻烦,可能会导致数据的篡改,而且还很难排查出错误。
int fun()
{
    int *p;
    *p = 200;
}

例子忘了给P初始化,也忘了赋值,如果p中的随机值恰好指向某个可以操作的空间,
*p = 200这句话是没问题的,但是很有可能把别的变量的空间给修改了

其实像这种野指针的问题,在开发时总会遇到个那么几次,如果在开发中不能将野指针排查出来的话,
就会一直遗留到产品中,在用户使用的过程中,问题随时都可能爆发出来


二、怎么解决野指针的问题

1. 在使用指针变量之前,记得赋值一个合法指针

int fun()
{
    int *p;
    p = malloc(siezof(int));  //p中有了合法指针后,就不会出现野指针的情况
    *p = 200;
}

仅靠赋值这种方式不是很靠谱,因为非常容易搞忘了。

2. 最好的方法:定义指针变量时初始化

容易忘记赋值,但是初始化确不容易忘记,所以我们在定义指针变量时,一定要记得初始化。

1)初始化为你需要的指针

int a = 10;
int *p = &a;

2)如果不知道初始化为何值的话,那就初始化为NULL(空指针)。

int *P = NULL;

有些时候确实不知道初始化为什么,因为需要在使用时才指定具体的指针,
像着这种情况的话,就初始化为NULL指针

疑问:初始化NULL的好处?

答:万一忘了赋值合法指针的话,解引用NULL会导指针错误,在编程调试时,
指针会导致程序被终止,程序员就回去排查错误,方便了程序员对指针错误的排查

如果不初始化为NULL的话,随机值可能指向了其它变量的空间,如果这个空间还可以操作的话,
程序表面上会正常运行,但是可能篡改其它变量的数据,程序得不到正确的计算结果,这样的错误更难搞定

3. 更严谨的使用指针

如果更严谨一点的话,我们在使用应该加上if(NULL != p)的判断

int *p = NULL;

if(NULL != P)
{
    *p = 200;
}

但是如果所有的指针,都按照这个套路来使用的话,写代码就太累了,
所以一般都不会这么麻烦,不过对于非常重要的指针来说,我们可以加这样的判断


三、 NULL指针

1. NULL宏被定义在什么地方

NULL这个宏被定义在了C标准库的stddef.h中,定义形式如下,

#if defined(__cplusplus)
#define NULL 0
#else
#define NULL ((void *)0)
#endif

我们知道C++是兼容C的,所以stddef.h既可以被C使用,也可以被C++使用,
C++中使用时,NULL0,在c中使用时NULL((void *)0)

这两种情况的值一样,唯一所不同的只是类型,0的类型时int((void *)0)的类型时void *
至于为什么会有这样的区别,我们暂且不关心,现在只需要记住,在CNULL(void *)0即可

2. “0” 地址

NULL这个空指针就是0地址,0地址要么不对应实际空间,要么就是不能访问,
所以对NULL指针进行解引用时,会导致指针错误

如果指针变量是全局变量的话,其实可以不用初始化NULL,因为全局变量不初始化时,默认就是0


四、段错误

什么是段错误

这个实际上Linux下指针错误的叫法,英文叫Segmentation fault,翻译为中文就是“段错误”

疑问:那么为什么将指针错误说成是段错误呢?

答:应该与程序的内存结构有关,因为程序的内存结构是由.text.rodata.data.bss、堆、栈等组成个,
我们可以将.text等称为Segment(段),如果指针有问题的话,就可能会导致放问错误的Segment,因为此就称为了段错误

比如:

#include <stddef.h>
int main(void)
{
    int *p = NULL;
    *p = 200;
    return 0;
}

Linux 下直接报 Segmentation fault(段错误):

$ gcc main.c
$ ./a.out 
Segmentation fault

windows 下:

Process finished with exit code -1073741819 (0xC0000005)

五、大段错误和小段错误

1. 大段错误

指针所指向的空间不存在,这种就是大段错误

2. 小段错误

指针所指向的空间是存在的,但是由于访问权限有限制,比如想写数据,但是空间只允许读数据,
像这种权限所导致的指针错误,就是小段错误