C语言指针:野指针 文章目录一、野指针1. 野指针的概念2. 产生原因3. 如何规避野指针二、assert断言函数2.1 **assert**的优点2.2 **assert**的缺点一、野指针1. 野指针的概念指向位置是不可知的、随机的、不正确的、没有明确限制的指针就叫野指针。2. 产生原因野指针产生的原因有(1) 指针未初始化创建指针变量时未对其进行初始化赋值则这个指针指向的位置是随机的。#includestdio.hintmain(){int*p;//局部变量指针未初始化默认为随机值return0;}(2) 指针指向的空间被释放①如果一个(局部)变量出了作用域或者是这个变量的生命周期结束了那变量就会被销毁变量所占的内存会还给操作系统此时如果还使用指针访问该变量那就会出现野指针编译器就会报错。#includestdio.hint*test(){intn10;returnn;}intmain(){int*ptest();printf(%d\n,*p);return0;}②指针被free之后没有被置为NULL。对指针进行free只是把指针所指向的空间释放掉但并没有把指针本身置为空此时指针指向的就是垃圾内存所以释放后的指针应该立即置为NULL养成良好的编程习惯以防产生野指针。(3) 指针越界访问在使用指针访问数组元素时超出数组的范围就会造成非法访问因为那块空间不属于数组的范围就会出现野指针#includestdio.hintmain(){intarr[10]{0};int*parr[0];inti0;for(i0;i10;i){//当指针指向的空间超出了数组arr的范围时p就是野指针*(p)i;}return0;}3. 如何规避野指针(1)指针初始化如果明确知道指针指向哪里就直接赋值地址如果不知道指针应该指向哪里可以给指针赋值NULL。NULL是C语言中定义的一个标识符常量值是00也是地址这个地址是无法使用的读写该地址会报错。正确使用指针示例#includestdio.hintmain(){intnum10;int*p1num;int*p2NULL;return0;}(2)注意指针越界一个程序向内存申请了哪些空间通过指针也就只能访问哪些空间不能超出范围访问超出了就是越界访问就会出现野指针。(3)指针变量不再使用时及时置为NULL指针使用之前检查其有效性当指针变量指向一块区域的时候我们可以通过指针访问该区域后期不再使用这个指针访问该空间的时候我们可以把该指针置为NULL。因为约定俗成的一个规则就是∶只要是NULL指针就不去访问同时使用指针之前可以判断指针是否为NULL。(4)避免返回局部变量的地址通过上面的例子就可知道局部变量一旦离开了作用域就会被销毁空间被释放此时不能再使用这块空间的指针来访问此空间。二、assert断言函数assert断言函数用于在程序运行过程中捕捉程序的错误。在大部分编译器下assert是一个宏在少数编译器下assert就是一个函数。assert函数在程序运行时会对某种假设条件进行检测如果条件成立程序就继续往下执行如果条件不成立就会捕捉到这种错误并打印出错误信息终止程序运行。assert函数包含在assert.h这个头文件中assert翻译过来的意思就是“断言”。所以可以使用assert来判断指针是否为NULL:assert(p!NULL);上面的代码在程序运行到这一行语句时验证变量p是否等于NULL。如果确实不等于NULL程序继续运行否则就会终止运行并且给出报错信息#includestdio.h#includeassert.hintmain(){int*pNULL;assert(p!NULL);return0;}运行结果由上图assert接收一个表达式作为参数。如果该表达式为真(非零)assert不会产生任何作用程序继续运行。如果该表达式为假(零)assert就会报错在标准错误流stderr中写入一条错误信息之后显示没有通过的表达式以及包含这个表达式的文件名和行号。关于流的概念后面会学习。2.1assert的优点assert不仅能自动标识文件和出问题的行号而且它还具备一种无需更改代码就能开启或关闭的机制如果已经确认程序没有问题不需要再做断言就在#include assert.h语句的前面定义一个宏NDEBUG它的意思是No Debug(一旦定义了宏NDEBUGassert就会失效)#defineNDEBUG#includeassert.h然后重新编译程序编译器就会禁用文件中所有的assert语句。如果程序又出现问题可以移除这条#define NDEBUG指令(或者把它注释掉)再次编译这样就会重新启用assert语句。2.2assert的缺点assert的缺点是因为引入了额外的检查增加了程序运行的时间。一般我们在Debug调试版本中使用assert而在Release发行版本中选择禁用assert。在VS这样的集成开发环境中在Release版本中assert直接就被优化掉了。这样在Debug版本中使用assert有利于程序员排查问题而在Release版本中不影响用户使用程序时的效率。