C/C++指针之空指针,野指针

1. 简介

  • C/C++指针常常让程序员很头疼。本文详细介绍C/C++的空指针和野指针。

2. 空指针

  • NULL指针,他作为一个特殊的指针变量,让它指空,表示不指向任何地址。

  • 对一个NULL指针解引用是一个非法的操作,所以在对指针解引用之前必须确保它不是一个NULL指针。

    if (p != NULL{
          
          
    	*p = 1; //如果指针不为空指针,则对指针进行操作
    }
    else
    {
          
          
    	return 0//空指针,退出
    }
    

3. C++11中的空指针

  • C++11引入了nullptr关键字来表示指针空值。
  • 用0和NULL表示空指针会产生歧义,建议用nullptr表示空指针,也就是(void*)0
    int main()
    {
          
          
    	//空指针定义
    	int* p1 = NULL;
    	int* p2 = 0;
    	//推荐
    	int* p3 = nullptr;
    	
    	return 0;
    }
    
  • 为了提高代码的健壮性,在后续表示指针空值时建议最好使用 nullptr 。
  • nullptr是对NULL的一个升级,因此在以后的初始化空指针时,建议大家使用nullptr。

4. 空指针的使用场景

4.1 指针初始化为空指针

  • 在良好的C/C++编程习惯中,声明一个变量时最好给这个变量赋一个合适的初始值,否则就有可能出现不可预料的错误。

  • 在C++中创建指针时,如果没有给指针初始化,计算机将分配用来存储地址的内存(指针的内存),但不会分配用来存储指针所指向的的数据的内存。

    int* p;    //分配用来存储地址的内存(分配指针的内存),这里并不知道指针指向哪块内存
    *p = 1;     //给指针指向的内存赋值
    
  • 上述代码中没有赋予指针所指向的数据的内存,会照成难以预料的后果。

  • 为了避免这个问题,我们都要给指针进行初始化。通常我们都是这样来初始化指针的。

    int main()
    {
          
          
    	//空指针定义
    	int* p1 = NULL;  //创建p1指针;p1指空,表示不指向任何地址。
    	int* p2 = 0;
    	
    	 //推荐
    	int* p3 = nullptr;
    	return 0;
    }
    

4.2 操作指针之前判断指针是否为空

  • 在程序中要增加判断指针是否为空的代码,防止对空指针解引用造成系统崩溃,增强函数的健壮性

    if (p != NULL{
          
          
    		*p = 1; //如果指针不为空指针,则对指针进行操作
    	}
    	else
    	{
          
          
    		return 0//空指针,退出
    	}
    

5. 野指针

  • 野指针,也就是指向不可用内存区域的指针。如果对野指针进行操作,将会使程序发生不可预知的错误,甚至可能直接引起崩溃 。

  • 野指针不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是野指针是很危险的,也具有很强的掩蔽性,if语句对它不起作用。

  • 造成野指针的常见原因有三种:

  1. 指针变量没有被初始化 。任何指针变量刚被创建时不会自动成为NULL指针。在Debug模式下,VC++编译器会把未初始化的栈内存上的指针全部填成 0xcccccccc ,当字符串看就是 “烫烫烫烫……”;会把未初始化的堆内存上的指针全部填成 0xcdcdcdcd,当字符串看就是 “屯屯屯屯……”。把未初始化的指针自动初始化为0xcccccccc或0xcdcdcdcd,而不是就让取随机值,那是为了方便我们调试程序,使我们能够一眼就能确定我们使用了未初始化的野指针。在Release模式下,编译器则会将指针赋随机值,它会乱指一气。所以,指针变量在创建时应当被初始化,要么将其设置为NULL,要么让它指向合法的内存。

  2. 指针指向的内存被释放了,而指针本身没有置NULL 。对于堆内存操作,我们分配了一些空间(使用malloc函数、calloc函数或new操作符),使用完后释放(使用free函数或delete操作符)。指针指向的内存被释放了,而指针本身没有置NULL。通常会用语句if (p != NULL)进行防错处理。很遗憾,此时if语句起不到防错作用。因为即便p不是NULL指针,它也不指向合法的内存块。所以在指针指向的内存被释放后,应该将指针置为NULL。

  3. 指针超过了变量的作用范围 。即在变量的作用范围之外使用了指向变量地址的指针。这一般发生在将调用函数中的局部变量的地址传出来引起的。这点容易被忽略,虽然代码是很可能可以执行无误,然而却是极其危险的。局部变量的作用范围虽然已经结束,内存已经被释放,然而地址值仍是可用的,不过随时都可能被内存管理分配给其他变量。

猜你喜欢

转载自blog.csdn.net/weixin_44710103/article/details/130975724