200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > 【C语言】指针初识(2)——野指针

【C语言】指针初识(2)——野指针

时间:2023-11-06 20:59:12

相关推荐

【C语言】指针初识(2)——野指针

野指针

概念:野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)

目录

一、野指针成因

1、指针未初始化

2、指针的越界访问

3、指针指向的空间释放

二、 如何规避野指针

一、野指针成因

1、指针未初始化

例:

int main(){int* p;*p = 10;return 0;}

代码中p没有初始化,意味着没有明确指向

而对于一个局部变量不初始化的话,放的就是随机值

*p = 10;

此时的p就是野指针(非法访问,当没有初始化时,放入随机值,而*p进行解引用时,通过*p所找到的地址并非是属于我们的)

2、指针的越界访问

int main(){int arr[10] = { 0 };int* p = arr;int i = 0;for (i = 0; i <= 10; i++){*(p++) = i;}return 0;}

当i<10时,p还不是野指针

当i=10时,指针p就超出了数组arr的范围,p就是野指针,用VS编译器运行会出现:

百度直译过来就是:运行时检查失败2-变量“arr”周围的堆栈已损坏。

一般报这种错误,都是内存越界,着重检查:

(1)、多维数组初始化是否有误

(2)、数组下标调用是否越界

3、指针指向的空间释放

int* test(){int a = 20;return &a;}int main(){int* p = test();printf("%d\n", *p);return 0;}

在以上代码中,看似没有问题,但是这里的p其实就是一个野指针。为什么这样说呢?

原因:当我们调用函数test,调用结束后,返回了一个int*的类型,也就是将a的地址返回到调用函数的地方,即赋给了p,值得注意的是,a这个变量是我们在调用函数时,临时创建的一个变量,函数调用完毕,则那一块内存空间就会被销毁掉,所谓销毁就是将相应的空间还给了操作系统。

这里可能会有人说,不对呀,我运行了,结果是正常的呀,没什么问题的。

啊啊啊,一定不要这样想啊!我打个比方,你的一个好朋友,她给了你一个地址,你通过这个地址就可以去找到她,但是,你们俩吵架了,她悄悄搬家了,却没有告诉你,你依然通过那个地址可以找到那个地址,但是,房子里面却住了别人。

而在上述代码中,你之所以还能将a的值打印出来,那是因为你的好朋友虽然和你吵架了,但她还没有找到合适的地方搬走,但此时你再去找她,是不太合适的,换句话讲,你是无法预知打开门的是不是她,充满了不确定性,所以说p为野指针。

咱们做个测试,因为函数test()的空间已经还给操作系统了,所以我们,再次使用系统中的内存空间,就有可能会影响*p的值

代码:

#include<stdio.h>int* test(){int a = 20;return &a;}int* test1(){int b=5;return &b;}int main(){int* p = test();int* p1 = test1();printf("%d\n", *p);return 0;}

在这里,我们在上述代码中,又定义了一个函数test1(),并调用了它一次,而我们还是继续打印*p,注意啊,打印的还是*p,不是*p1,但我们此时来观察输出,如图:

为什么呢?

因为上述中,我们调用完test(),相应空间就还给操作系统了,也就是说,调用test1()时,test1()会向系统申请一块空间,而操作系统是完全可以将刚才分配给test()的空间再次分配给test1(),所以在test1()中,将其对应的地址内容改变成了5。

通俗的说,就是你的好朋友20,已经搬走了,5住进去了,你现在再通过旧的地址去找到的房子时,开门的人就是5了。

二、 如何规避野指针

1、指针初始化

如果有确切的值就给它初始化为相应的值,如果没有,则初始化为NULL

2、小心指针越界

这个问题在自己编写代码时,就需要注意了,因为编译器不会报错

3、指针指向空间释放,则立马将其置为空指针(NULL)

4、避免返回局部变量的地址

5、指针使用之前检查其有效性

在使用前判断指针是否为空指针(NULL),因为空指针它不指向任何对象

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。