初阶指针(2)野指针(野指针的成因 如何规避野指针)

指针:野指针

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

一、野指针

野指针的成因

1.指针未初始化

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

这个代码指针变量p没有初始化 ,就意味着,没有明确的指向。

一个局部变量不初始化的话,放的是随机值:0xcccccccc(函数栈帧的空间会被初始化一部分内容)

p里面放的是0xcccccccc这样的值,这样一个值放到p里面的时候意味着放的是一个地址,就是把0xcccccccc这样一个值当成p里面放的那个的地址,* p即对那个随机值的地址进行解引用,访问一块空间,而那个地址所指向的空间并不是p的,即那个地址是一个非法的地址,所以*p通过那个地址所找到的空间也不属于p,属于非法访问内存。

当我们用上面这种情况下的p时,这里的p就是野指针。

2.指针越界访问

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

在这里插入图片描述
当指针指向的范围超出数组arr的范围时,p就是野指针。

3.指针指向的空间释放

int* test()
{
	int a = 10;
	return &a;
}
int main()
{
	test();

	int* p = test();

	return 0;
}

首先我们进入main函数要调用test(),进去调用的时候创建了a,a是一个局部变量,将10放进a里,假设a的地址是0x0012ff40,而return &a,将其返回到p里面去了,注意,这个时候p里面放的就是0x0012ff40这个地址,但是当我们把这个地址返回来的时候,这个a空间因为它是局部的,一旦出了test这个函数的时候,它就销毁了,所谓的销毁,就是把这块内存还给操作系统里,大家注意它把那块空间还给了操作系统所以我们是不可以使用它的,但是p里面还保存了这块空间的地址,那就是说p其实是有能力找到这块空间,但是当p找到这块空间的时候,是不能访问使用这块空间的。所以p在这块也是野指针。

如何规避野指针

1.指针初始化
2.小心指针越界
3.指针指向的空间释放及时值NULL
4.避免返回局部变量的地址
5.指针使用之前检查有效性

int main()
{
	int a = 0;
	int* p = &a;
	*p = 20; 
	return 0;
}

明确的给指针进行初始化,但是有时候会出现一种情况,暂时不知道给指针初始化什么值,那么此时我们给它初始化成空指针。

int main()
{
	int* p2 = NULL;//NULL就是0
	*p2 = 100return 0;
}

在这里插入图片描述
此时,我们调试起来发现,程序崩溃了,写入访问权限冲突,什么意思呢,就是内存里面有些地址是不能访问的,比如说NULL地址是不允许访问的,所以我们以后在使用指针的时候,当一个指针变量不知道初始化什么值的时候,给它初始化成空指针,注意,当用这个指针的时候如下代码:

int main()
{
	int* p3 = NULL;
	if (p3 != NULL)
	{
		*p3 = 100;
	}
	  return 0;
}

因为我们不知道给p3赋什么值,所以我们给p3先赋了空指针,我们再用它之前判断它如果不是空指针,如果不是,那我们就用它,那此时*p3解引用然后赋100进去是可以的,因为它不等于空指针说明它已经有有效的指向了,所以就可以解引用它,这样做就可以在一定程度上避免指针出现问题。但是这种写法是避免不了指针指向的范围超出数组arr的范围时这种错误的。

我们可以野指针看成一条野狗,你在路上看到野狗,害怕它伤人,你会怎么办呢,是我的话,我可能是想办法把这条野狗想办法栓到一棵树上,这个时候,如果没人靠近野狗的话,它是不是就是不会伤害人,当我们不知道给p2赋什么值的时候,就给它赋空指针,就相当于把野狗拴到一个树上,这个时候相对比较安全了,但是这个时候,你明明看到这个野狗栓到树上了,你非得跑过去在树底下尿尿,这个时候就相当于上面的解引用p2,并赋值100,这个时候野狗是一定会伤害你的。

指针的问题五花八门在使用的时候是非常危险的,建议大家在使用指针的时候一定要小心谨慎!!!

  • 20
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

马尔科686

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值