空指针防护

空指针NULL、野指针、通用指针

什么是指针

假设 有语句

int a=10;

那么编译器就在内存中开辟1个整型单元存放变量a,我们假设这个整型单元在内存中的地址是 0x1000;那么内存0x1000单元中存放了数据10,每次我们访问a的时候,实际上都是访问的0x1000单元中的10.

现在定义:

int *p;
p = &a;

当编译器遇到语句int *p时,它也会在内存中给指针变量p分配一个内存单元,假设这个单元在内存的编址为0x1003;此时,0x1003中的值是不确定的,(因为我们没有给指针赋值),当编译器遇到了p = &a时,就会在0x1003单元中保存0x1000,请看,这就是说:(指针变量p代表的)内存单元0x1003存放了变量a的内存地址!

用通俗的话说就是p指向了变量a

p=NULL,就是说:内存单元0x1003不存放任何变量的内存地址。

空指针

空指针是一个特殊的指针值,也是唯一一个对任何指针类型都合法的指针值。指针变量具有空指针值,表示它当时处于闲置状态,没有指向有意义的东西。

空指针用0表示,C语言保证这个值不会是任何对象的地址。给指针值赋零则使它不再指向任何有意义的东西。为了提高程序的可读性,标准库定义了一个与0等价的符号常量NULL.

程序里可以写

p = 0; 

或者

p = NULL;

两种写法都把p置为空指针值。相对而言,前一种写法更容易使读程序的人意识到这里是一个指针赋值。

我们印象中C语言的指针都有类型,实际上也存在一种例外。这里涉及到通用指针,它可以指向任何类型的变量。通用指针的类型用(void *)表示,因此也称为void 指针

int n=3, *p;
void *gp;
gp = &n;
p=(int *)gp1;

野指针

野指针,也就是指向不可用内存区域的指针。通常对这种指针进行操作的话,将会使程序发生不可预知的错误。
“野指针”不是NULL指针,是指向“垃圾”内存的指针

人们一般不会错用NULL指针,因为用if语句很容易判断。

但是“野指针”是很危险的,if语句对它不起作用。

野指针的成因主要有以下三种:

  1. 指针变量没有被初始化。

任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。

  1. 指针pfree或者delete之后,没有置为NULL,让人误以为p是个合法的指针。

别看freedelete的名字很霸气(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。通常会用语句if (p != NULL)进行防错处理

但很遗憾,此时if语句起不到防错作用,因为即便p不是NULL指针,它也不指向合法的内存块。

例:

char *p = (char *) malloc(100);

strcpy(p, “hello”);

free(p); // p 所指的内存被释放,但是p所指的地址仍然不变

if(p != NULL) // 没有起到防错作用

strcpy(p, “world”); // 出错

另外一个要注意的问题:不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放。
栈内存存储的是局部变量,栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短
栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制回收。

  1. 指针操作超越了变量的作用范围。这种情况让人防不胜防

常用字符串判断空方法,防止空指针

 StringUtils.isNotBlank(null)      = false
 StringUtils.isNotBlank("")        = false
 StringUtils.isNotBlank(" ")       = false
 StringUtils.isNotBlank("bob")     = true
 StringUtils.isNotBlank("  bob  ") = true
 
 StringUtils.isBlank(null)         = true
 StringUtils.isBlank("")           = true
 StringUtils.isBlank(" ")          = true
 StringUtils.isBlank("bob")        = false
 StringUtils.isBlank("  bob  ")    = false

你可能感兴趣的:(嵌入式,Linux,指针)