当前位置: 首页 > 科技观察

详解C语言那些可怕的野指针

时间:2023-03-21 15:28:17 科技观察

1.什么是野指针?指针是C语言的灵魂,也是一个容易出错的难点。使用错误的指针将是一场灾难。指针变量的本质是一个值。这个特殊值是一个内存地址值,合法的内存地址包括定义变量(栈)的地址,malloc函数返回的申请堆内存的地址(但不是用free释放的,是在heap空间动态申请)需要注意的是,野指针不是NULL指针。通常NULL指针可以通过if语句来判断,但是C语言中并没有判断一个指针是否为野指针的方法!2、野指针是怎么来的?通常野指针是由于指针变量中存储的值不是合法的内存地址或指向不可用内存的指针造成的。而且,野指针往往会导致内存越界、段错误等难以发现的问题。下面分几种情况说说野指针的由来。局部指针变量未初始化//win10_64+vs2017//来源:科技让梦想更大//作者:李逍遥#include#includestructStudent{char*name;intnumber;};intmain(){structStudents;strcpy(s.name,"李逍遥");//OOPS!s.number=99;return0;}局部变量不像全局变量,不是会自动初始化为0assigned,pointersname指向的内存空间的地址是随机的,不能向随机地址空间写入数据。我们在定义局部指针变量时,要初始化为NULL,局部变量要初始化为0才能使用已经释放的指针//inwin10_64+vs2017//来源:科技让梦想更大//作者:李逍遥#include#include#includevoidfunc(char*p){printf("%s\n",p);free(p);}intmain(){char*s=(char*)malloc(5);strcpy(s,"李逍遥");//数组越界func(s);printf("%s\n",s);//哎呀!使用已释放的指针sreturn0;}malloc申请的堆空间被释放后,意味着这块内存被归还到freelist,其他程序就可以使用这块空间了。如果其他程序使用这个空间,其他程序可能会莫名其妙地关闭。释放后,将指针变量的值赋给NULL。指针指向的变量先于指针销毁//win10_64+vs2017//来源:科技让梦想更大//作者:李逍遥#includechar*func(){charp[]="lixiaoyao";returnp;}intmain(){char*s=func();printf("%s\n",s);//OOPS!return0;}调用func函数时,栈区存放的是局部数组p和func返回后,栈顶指针退出,占用的内存已经释放。此时指针s指向一个释放的栈空间。如果修改了栈空间的值,就不会打印出预期的结果,s就变成了野指针,所以我们绝不能在函数中返回局部变量和局部数组的地址。指针操作错误//win10_64+vs2017//来源:科技让梦想更大//作者:李逍遥#includevoidmain(){inta[10]={1,2,3,4,5,6,7,8,9,10};int*p;for(int*p=&a[9];p>=a;){*--p=0;}}在程序中第一个元素a之后数组[0]清空,指针p的值继续递减,进行下一次比较操作,结??束循环。但是表达式p>=a(p>=&a[0])的值是未定义的。为避免这种情况,一定要确保字符数组以'\0'结尾。为了防止内存越界,自己写的内存相关函数需要指定正确的长度信息。进行了错误的类型转换//inwin10_64bit+vs2017//来源:科技让梦想更大//作者:李逍遥#include#includeintmain(){inta=1;intp=&a;printf("%d\n",*((int*)p));/*64位下输出错误,32位下输出a的值1*/return0;}以上程序在64位下输出错误,32位下a的值为1。我们在写嵌入式程序的时候,会把一个int类型的数据强行转换成指针类型来表示寄存器的地址。这时候就需要注意了。如何避免野指针?知道了野指针产生的原因,规避方法就出来了。在取消引用指针之前,请确保指针指向绝对可用的空间。在定义指针时,同时将其初始化为NULL。在解引用指针之前,先判断指针是否为Null。使用指针后,将其赋值为NULL。在使用指针之前,将其分配给一个可用的地址空间